やりたいこと
- SwiftでWkWebView(Angular)を動作させ、WebView側からSwiftの処理を発火させたい
- なおかつ普通のブラウザからでもAngularを動作させたい
SwiftでWkWebView(Angular)からの処理を受ける部分
今回Swiftでは下記のようなWkWebViewから処理を受けるコードを書いていました(実際の実装とは一部異なります)
extension WKWebView: WKScriptMessageHandler { /// WkWebViewから実行されるpostMessageを有効化。外部のファイルから当メソッドは実行される。 public func enablePostMessage() { configuration.userContentController.add(self, name: "anyActionByWebView") } /// WkWebViewから実行されるpostMessageのnameから実行処理を判別する。 public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { if(message.name == "anyActionByWebView") { print("body: \\(message.body)") } } }
WkWebView(Angular)からSwiftへ処理を渡す部分(変更前)
最初、以下のコードを書いていましたがmacOSのChromeでデバッグしたところうまく動作しませんでした。
declare var webkit; // Swiftで定義したmessage.nameである"anyActionByWebView"を指定してpostMessage()する。 webkit.messageHandlers.anyActionByWebView.postMessage("post message for swift!");
実行時に下記のエラーが発生します。
Error: Uncaught (in promise): ReferenceError: webkit is not defined ReferenceError: webkit is not defined at ItadakimasuCompareService.<anonymous> (itadakimasu-compare.service.ts:31) ...
webkit
が未定義と言われました。
macOSのChromeで動作させた場合は未定義と言われるのですが、iOSのWkWebViewからこのソースコードを実行するとエラーは出ません。動作させる環境によって実装が異なることが原因のようです。
というわけで、webkit
が未実装のケースも想定した次のソースコードに書き替えました。
WkWebView(Angular)からSwiftへ処理を渡す部分(変更後)
// window.webkitの存在チェックをした上でpostMessageする if ((window as any)?.webkit) { (window as any)?.webkit.messageHandlers.anyActionByWebView.postMessage("post message for swift!"); }
これでmacOSからAngularをデバッグした場合はエラーを吐かなくなりました。
Swiftでだけ実行させたい処理があるかは微妙ですが…😑