iPhoneのネイティブ機能をWebViewから呼び出す方法(2)

アドウェイズエンジニアの波切です。
今回は、「iPhoneのネイティブ機能をWebViewから呼び出す方法」の2回目として、WebView内のJavascriptから、ネイティブの機能を呼び出し、かつ値を受け取るための方法についてご紹介いたします。

・値を受け取るための仕組み

前回(1)の際は、UIWebViewクラスのshouldStartLoadWithRequestメソッドを使って、処理をフックしました。
この方法では、処理をフックは出来ますが、値を返すことは出来ませんでした。

今回は値を返すために、NSURLProtocolというクラスを使います。
NSURLProtocolクラスを使うと、下図のように特定のURLで示される通信処理(request, response)を定義することが出来ます。


Untitled

今回は、上記の仕組みを使って前回と同じサンプルを再実装してみようと思います。

Untitled
システムの概要図(クリックすると拡大します)

・実装の説明

それでは、早速コードを見て行きましょう!

(1)NSURLProtocolクラスの実装

まずは、NSURLProtocolを継承して、NativeProtocolというクラスを実装してみます。
このクラスでは、URLスキームに対応する通信処理をメインに実装します。

実装が必須なメソッドは、下記の4つとなります。

canInitWithRequest
canonicalRequestForRequest
・startLoading
・stopLoading

これらを実装しないと実行時にエラーとなってしまいますので、ご注意を…。



このクラスの実装の中心となるのは、startLoadingメソッドで、通信が始まった時に呼び出されるもので、この呼び出しの中でネイティブ側の処理を行い、結果をレスポンスとして返していきます。

肝心のネイティブ処理の中身がこのクラスにはないのですが、この部分はWebViewを持つ、WebViewControllerクラスに実装してあります。NativeProtocol内では処理をするのに必要な参照がないので、NSNotificationCenterを使って、WebViewControllerに処理を通知しています。

結果を返す部分に相当する部分が、sendResponseメソッドです。
このメソッドに文字列を渡すことで、通信のレスポンスとして引数で与えられた文字列を返す実装となっています。このメソッドは、次に説明するWebViewControllerの中で使われています。

(2)WebViewControllerの実装

WebViewControllerでは、ネイティブ処理を実際に行う部分をコーディングしています。



invokeNativeMethodが今回のネイティブ処理のハンドリングを行っているメソッドです。

前回のブログでご紹介したinvokeNativeMethodのソースと、今回のブログのinvokeNativeMethodのソースを比較して頂けると分かると思いますが、今回のソースでは、レスポンスオブジェクトへの参照があるため、結果を返すことが可能になっています。

(3)Web側の実装




ネイティブ側の実装方法の変更でWeb側の実装がかなりすっきりしたことがお分かり頂けるかと思います。

特に以下の点はメリットといえます。

・nativeプロトコルを使ったajax通信でネイティブ側の機能にアクセスできる
・値の返却が必要な場合は、ajaxのレスポンスとして受け取ることが出来る。

・まとめ

NSURLProtocolを用いることで、WebView内のJSからネイティブ機能を呼び出して、値を返すことが出来ました。
また、JS内からネイティブを呼び出す際も、ajax処理としてまとめることが出来て非常にすっきりさせることが出来ました。
NSURLProtocolクラスは、他の用途にも使える重要な拡張手段だと思うので、覚えておくと非常に便利だと思います。

※今回のソース一式は、下記のURLからダウンロードできます。

https://github.com/fugafigs/NativeFromWebView2