Swift・iOS

Swiftを中心に学んだことを記録に残すブログです。技術に関係ない記事もたまに書いています。

【Swift】WKWebViewで表示しているページのURLとタイトルを取得する

 

はじめに

【SwiftUI】WKWebViewを使えるようにする - Swift・iOSの続きです。今回はWKWebViewで表示しているページのURLとタイトルを取得する方法について記載します。

 

開発環境

 

本題

該当のメソッド

WKNavigationDelegateの"webView(_:didFinish:)"で表示しているページの情報を取得できる。

参考:

https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    // 表示しているページのURL
    print(webView.url?.absoluteString ?? "")
    // 表示しているページのタイトル
    print(webView.title ?? "")
}

 

SwiftUIでの実装例

【SwiftUI】WKWebViewを使えるようにする - Swift・iOSに該当のメソッドを追加したコードです。

WebView.swift

import SwiftUI
import WebKit

struct WebView: UIViewRepresentable {
    var urlString: String
    
    class Coordinator: NSObject, WKUIDelegate, WKNavigationDelegate {
        var parent: WebView
        
        init(_ parent: WebView) {
            self.parent = parent
        }
        
        // "target="_blank""が設定されたリンクも開けるようにする
        func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
            if navigationAction.targetFrame == nil {
                webView.load(navigationAction.request)
            }
            return nil
        }
        
        // URLごとに処理を制御する
        func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
            if let url = navigationAction.request.url?.absoluteString {
                if (url.hasPrefix("https://apps.apple.com/")) {
                    guard let appStoreLink = URL(string: url) else {
                        return
                    }
                    UIApplication.shared.open(appStoreLink, options: [:], completionHandler: { (succes) in
                    })
                    decisionHandler(WKNavigationActionPolicy.cancel)
                } else if (url.hasPrefix("http")) {
                    decisionHandler(WKNavigationActionPolicy.allow)
                } else {
                    decisionHandler(WKNavigationActionPolicy.cancel)
                }
            }
        }
        
        // 表示しているページ情報
        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            // 表示しているページのURL
            print(webView.url?.absoluteString ?? "")
            // 表示しているページのタイトル
            print(webView.title ?? "")
        }
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    func makeUIView(context: Context) -> WKWebView {
        let webView = WKWebView()
        
        return webView
    }
    
    func updateUIView(_ webView: WKWebView, context: Context) {
        // makeCoordinatorで生成したCoordinatorクラスのインスタンスを指定
        webView.uiDelegate = context.coordinator
        webView.navigationDelegate = context.coordinator
        
        // スワイプで画面遷移できるようにする
        webView.allowsBackForwardNavigationGestures = true
    
        guard let url = URL(string: urlString) else {
            return
        }
        let request = URLRequest(url: url)
        webView.load(request)
    }
}

 

おわりに

デリゲートメソッドで取得したページ情報の共有方法ですが、SwiftUIの場合は、@Bindingなどで監視するよりも、NotificationCenterなどの通知を使用した方が呼び出し側の実装がすっきりするような気がしました。

 

参考