iOSでガワネイティブでWebView上で動かしているJSとSwiftの基本的なやりとりを試したけど大事なことが抜けていた。件の記事でJSからSwiftを呼び出してあとはネイティブに任せっきりという処理はできるが、ネイティブからなにか情報を取得することを試していなかった。
JSからネイティブを呼び出し結果を受け取る方法
webView:shouldStartLoadWithRequestではリクエストされたURLに遷移するかどうかは制御できるが、値の取得はできない。値を取得するには別の仕組み、NSURLProtocolというものを使う。
NSURLProtocolを継承したクラスを作りシステムに登録するとURLリクエストのたびにcanInitWithRequestが呼び出されるので、フックしたい場合にはtrueを返してその後呼び出されるstartLoadingでレスポンスを返すとブラウザに渡される。JSからはAjaxでフックされるURLを叩いて結果を得るようにすればネイティブから値を取得することができる。
カスタムのURLProtocolクラスを定義する
// MyURLProtocol.swift |
作ったURLProtocolを登録する
ViewControllerのviewDidLoadかなにかに以下を追加すると、すべてのWebViewのURLリクエストがフックされる:
NSURLProtocol.registerClass(MyURLProtocol) |
アプリの終了などで使わなくったらunregisterしてやること:
NSURLProtocol.unregisterClass(MyURLProtocol) |
JavaScriptからの呼び出し
通常のAjaxのようにXmlHttpRequestを使うが、違いとしてはAsyncじゃなく同期にしてやると違和感がないのではないかと思う(JS的には結局コールバックを使うことになるが…):
// test.js |
カスタムのURLProtocolでリクエストに対する結果を返す
自分で定義したMyURLProtocolのstartLoadingでリクエストに対してクライアントになにか結果を返してやる必要がる。簡単に返せるように、sendBackEmptyとsendBackPlainTextというメソッドを用意してやった:
// MyURLProtocol.swift |