ローソンデジタルイノベーション テックブログ

ローソンデジタルイノベーション(LDI)の技術ブログです

【iOS】WebViewにてSPAの画面遷移を検知する方法

はじめに

こんにちは、ローソンデジタルイノベーション(LDI)でiOSエンジニアを担当している山形です。

今回は、WebViewを使用した画面実装における、ちょっと工夫が必要な実装方法についてお話しします。

具体的には、SPA(Single Page Application)で構築されたWebサイトをWebViewで表示する際、画面遷移をネイティブ側で検知したい場面がありました。

通常のWebページ遷移とは異なり、SPAの画面遷移(History APIを用いた遷移)はWKNavigationDelegateのメソッドが呼ばれないことがあり、一工夫必要だったのでその方法を共有します。

開発環境

macOS:Sequoia 15.6
Xcode:26.0
サポートOS:iOS15〜

課題:WKNavigationDelegateが呼ばれない

通常、WKWebViewの画面遷移はWKNavigationDelegatewebView(_:decidePolicyFor:decisionHandler:)などで検知できます。

しかし、SPA(シングルページアプリケーション)では、最初のHTML読み込み後にJavaScriptを使用してコンテンツを動的に書き換えることで画面遷移を表現します。
具体的には、Next.jsなどのフレームワークでは、History API (history.pushStatehistory.replaceState) を使用してURLを書き換えています。

この場合、あくまでJavaScriptによるDOMの書き換えとURLバーの更新が行われているだけで、ブラウザのページ全体の再読み込みは発生しません。そのため、ネイティブ側の WKNavigationDelegate のデリゲートメソッド(didFinishなど)はトリガーされないという特性があります。

これにより、例えば「特定の画面に遷移したらネイティブ側のUIを変更したい」といった要件が実現できなくなってしまいます。

解決策:WKWebView.urlをKVOで監視する

ポイント

前述の通り、SPAの遷移ではデリゲートメソッドは呼ばれませんが、URL自体は更新されています

そこで、WKWebViewurlプロパティがKVO(Key-Value Observing)に準拠している点を利用し、このプロパティの変更を直接監視することで遷移を検知します。

前提条件

この方法は、SPA側で画面遷移時にURL(パスやクエリパラメータ)が変更されること が前提となります。 URLが変更されないDOMの書き換えのみの遷移や、URLが変わらないモーダル表示などは検知できませんのでご注意ください。

実装例

NSKeyValueObservationを使用してwebView.urlの変化を監視するシンプルな実装例をご紹介します。

final class WebViewController: UIViewController {

    var webView: WKWebView!

    // 省略...

    // URL監視用のObserverを保持
    private var urlObserver: NSKeyValueObservation?

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // URL監視の開始
        observeURL()
    }

    private func observeURL() {
        // KVOでurlプロパティの変更を監視
        urlObserver = webView.observe(\.url, options: .new) { [weak self] _, _ in
            guard let self,
                  let url = self.webView.url else { return }
            
            // 変更されたURLを検知
            print("Detected URL Change: \(url)")
            // 必要に応じてUIの更新処理などを呼び出す
            // self.updateUI(with: url)
        }
    }
}

まとめ

今回紹介した方法のポイントは以下の2点です。

  1. WKWebView.urlの監視: SPAの遷移(History APIによるURL変更)はデリゲートメソッドでは検知できませんが、WKWebViewurlプロパティ自体は更新されます。これをKVOで監視することで、ネイティブ側で検知可能になります。

  2. Observerの保持: observeメソッドが返すNSKeyValueObservationオブジェクトをメンバ変数として保持することを忘れないでください。これが破棄されると監視が停止します。

最後に

ここまで記事を読んでいただきありがとうございます!

WebViewとネイティブの連携は複雑になりがちですが、標準機能であるKVOを活用することで、シンプルにSPAの遷移検知を実現できました。同様の課題をお持ちの方の参考になれば幸いです。

今後もローソンデジタルイノベーションでは技術ブログを更新していきますので、是非「読者になる」で応援していただけますと幸いです。