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
コメント