LoginSignup
6
2

More than 1 year has passed since last update.

【Swift】SPAで作られたwebページをWebViewで扱う

Last updated at Posted at 2021-08-13

何が問題か?

WebView内のコンテンツがSPA(Single Page Application)で作られていると、ページ遷移しても期待したようにWKWebViewdelegateが呼ばれない場合があります。SPAは最初にhtmlを取得したらJavaScriptによって画面の書き換えを行うので、webページの読み込みが初回のみしか発生しないためです。

例えばwebコンテンツがページ遷移するたび、htmlのtitleタグの情報を取得しnavigationItem.titleにセットする場合を考えます。

普通のwebページなら読み込み完了のタイミングで以下のようにtitleをセットするので問題ありませんが、SPAだとこのdelegateは初回のみしか呼ばれません。そのため最初にセットされたtitlenavigationItemに残り続け、遷移先のtitlenavigationItemに反映されません。

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    guard let title = webView.title else { return }
    navigationItem.title = title
}

どうするか?

今回の例では以下のふたつを組み合わせて対応できます。

  • viewDidLayoutSubviews内でurlの変更を監視する
  • SwiftからJavaScriptを実行してtitleを取得する
class ViewController: UIViewController {

    var webView: WKWebView!
    private var urlObserver: NSKeyValueObservation?

    // SPAのwebページ遷移で呼ばれる
    override func viewDidLayoutSubviews() {
        urlObserver = webView.observe(\.url, options: .new) { [weak self] _, _ in
            guard let self = self else { return }
            self.setTitle()
        }
    }

    private func setTitle() {
        // jsのdocument.titleプロパティを実行
        let script = "document.title"
        webView.evaluateJavaScript(script) { (result, _) in
            self.navigationItem.title = result as? String
        }
    }
}

extension ViewController: WKNavigationDelegate {
    // 初回のWebView読み込み時によばれる
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        setTitle()
    }
}

以上のようにtitleを取得できますし、同じ要領でurlも取得可能です。

他の場面においてもSPAで構成されたwebコンテンツでWKWebViewdelegateを使用したい場合は、適宜urlの監視をうまく使ってやるのが有効かもしれません。

参考

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2