JavaScript
Swift

swift + javascript 値渡しでWKWebViewはすごかった

More than 3 years have passed since last update.

WebKitがでてしばらく経つのですが、Webと連携したものをしっかり作ったことがなかったので簡単にメモっときます。

javascript -> swiftへ値を渡してみます。


WKWebViewってなんだ?

いわゆるWebViewの拡張版と考えてもらえれば分かりやすいです。

特にjavascriptとの連携が強化されたものです。


WebViewで起きてしまった問題

WebViewから値を持ってくる時はどうしていたでしょうか?

例としてボタンが押された時に値をswift側に持ってきたい。

SwiftとJavascriptの通信を参考にこんな感じにやっていました。


javascript

location.href = "hoge:// {"url":"exsample.com","user":"tom"}"



ViewController

func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {

if navigationType == UIWebViewNavigationType.FromSubmit {
if request.URL!.scheme == "hoge" {
//処理
}
}
}


schemeで判定してあげていたのですが、hrefってURLですよね。

これだと文字化けしちゃいます。


Objective-Cではできそうなのがある

Objective-Cには

[webView stringByEvaluatingJavaScriptFromString: … ];

なんてものがある。でもswiftではなさそう。 swiftでもありました。

iOS:objective-cとjavaScriptの連携(1)


そうだWKWebViewを使おう

WKWebView and JavaScript in iOS 8 - using Swiftに良さげなやり方がありました。

これはもうWKWebViewを使うしかありません。


WKWebViewで値を持ってくる


下準備

プロジェクト > Build Phases > Link Binary With Libraries より

+ボタンを押して Webkit.frameworkを追加


WKWebViewを作成する

WKWebViewの今回の拡張

- WKScriptMessageHandler

- WKUserContentController

を使っていきます。


swiftでの処理

class ViewController: UIViewController,WKNavigationDelegate,WKScriptMessageHandlerと用意しておきます。

WKWebViewを置く時にWKUserContentControllerをおきます。


ViewController

            let webCfg:WKWebViewConfiguration = WKWebViewConfiguration()            

let userController:WKUserContentController = WKUserContentController()
userController.addScriptMessageHandler(self, name: "callbackHandler")
webCfg.userContentController = userController;
let wkWebView = WKWebView(
frame: CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height),configuration: webCfg)

これで WKWebViewで"callbackHandler"を呼ばれた時にuserControllerで処理することができます。


ViewController

func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {

if(message.name == "callbackHandler") {
print("JavaScript is sending a message \(message.body)")
}
}



javascriptの処理

以下の処理で開始されます。ボタンのonclickで呼ぶのが無難なんでしょうか。


javascript

webkit.messageHandlers.callbackHandler.postMessage(myjson);


これでmyjsonをswift上でmessageとして受け取れます。もちろん文字化けなんておきません。


最後に

あとは自由置き換えるなりできると思います。

WebKitの中を見ているとiOS9からの追加機能もちらほらあるので使ってみるのもいいかもしれません。いろいろ試してみようかな。

WKWebViewについてのまとめもあるのでみてみることをお勧めします。

WKWebViewに関する調査メモ


補足


Objective-Cには

[webView stringByEvaluatingJavaScriptFromString: … ];

なんてものがある。でもswiftではなさそう。


とありましたが

public func stringByEvaluatingJavaScriptFromString(script: String) -> String?

というものがありました。