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 |