WkWebView(Angular)からSwiftの処理を発火させる際に躓いたこと

やりたいこと
- 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でだけ実行させたい処理があるかは微妙ですが…😑