【Swift】WKWebViewでページ遷移をフックする

WKWebViewを使う際、特定のページ / サイトへの遷移をフックして、特別な処理を行いたいケースがあると思います。
このようなケースに対応するサンプルを紹介します。

ページ遷移をフックする

ページ遷移をフックするには、WKNavigationDelegateのwebView(_:decidePolicyFor:decisionHandler:)を使います。

// “https://www.apple.com/”への遷移は、標準ブラウザアプリで開くようにするサンプルです extension ViewController: WKNavigationDelegate { func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { guard let requestUrl = navigationAction.request.url else { decisionHandler(.allow) return } if requestUrl.absoluteString.hasPrefix(“https://www.apple.com/”) { // WebViewでの遷移をキャンセルして decisionHandler(.cancel) // 標準ブラウザアプリ(Safari等)で開く UIApplication.shared.open(requestUrl) } else { decisionHandler(.allow) } } }

フックした際、その遷移をWebView上で行いたくない場合は最後に「decisionHandler(.cancel)」を行い、WebView上での遷移をキャンセルします。
逆にWebView上で遷移してほしい時は「decisionHandler(.allow)」を呼び出して、WebView上での遷移を許可してあげます。

通常のページ遷移は上記delegateが呼ばれますが、javascriptのopen等、新しいウィンドウに対する表示リクエストの場合、WKUIDelegateのwebView(_:createWebViewWith:for:windowFeatures:)が呼ばれるため、必要に応じて、こちらにも類似の処理を入れましょう。

// “https://www.apple.com/”への遷移は、標準ブラウザアプリで開くようにするサンプルです extension ViewController: WKUIDelegate { func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? { guard let requestUrl = navigationAction.request.url else { return nil } if requestUrl.absoluteString.hasPrefix(“https://www.apple.com/”) { // 標準ブラウザアプリ(Safari等)で開く UIApplication.shared.open(requestUrl) // WebViewでの遷移をキャンセル return nil } else { let newWebView = WKWebView(frame: webView.frame, configuration: configuration) newWebView.load(navigationAction.request) newWebView.uiDelegate = self webView.superview?.addSubview(newWebView) return newWebView } } }

まとめ

javascriptのopen等の場合、WKUIDelegate側にも実装が必要な点は気づきにくく、落とし穴になりやすいので、参考になれば幸いです。

参考

本記事で紹介した処理のサンプルプログラムをGithubに公開しています。
https://github.com/u-pt/sample-hook-page-transitions-with-wkwebview

コメント

タイトルとURLをコピーしました