LoginSignup
0
0

WKWebViewのLocalStorageに設定した値がサーバー側で読み取れない

Posted at

結論として、WKUserScriptInjectionTimeatDocumentEndを設定していたことが原因だった。

事象

WKWebView生成時にWebViewのLocalStorageへ値を設定したあと、URLRequestでWebページを読み込む処理において、Web側でLocalStorageが読み取れない事象が発生した。

悩んだ原因

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)内でLocalStorageKeyの値を出力したときには値が確認できていたため「アプリ側では値はちゃんと設定できているな」と判断してしまった結果、事象の解決まで長引くことに・・・。

.swift
// webViewのローカルストレージにキーを設定
webView.configuration.userContentController.addUserScript(WKUserScript(
    source: "localStorage.setItem('\(localStorageKey)', '\(key)');",
    injectionTime: .atDocumentEnd,
    forMainFrameOnly: true
))
.swift
/// WebViewの読み込み完了時に呼び出される
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    webView.evaluateJavaScript("localStorage.getItem('key')") { result, error in
        if let error = error {
            print(error)
            return
        }
        print("LocalStorageKey: \(result ?? "nil")") // resultが出力される
    }
}

試したこと

  • アプリ側でLocalStorageに値を設定したあと、Sleep()で数秒ディレイをかけてからURLRequestする。
    →効果なし。変わらず。

  • サーバー側でリクエストを受けた後、数秒ディレイをかけてからLocalStorageを読み込む。
    →効果あり。
    ここでLocalStorageのセット or 読み込みのタイミングに問題があると把握。

  • 〜数週間放置〜

  • いい加減に対応しないといけなくなり、printデバッグしつつコードを見直していたところatDocumentEndが目について「ん?」となる。

    • atDocumentStart:Web ページのドキュメント要素の作成後、他のコンテンツをロードする前にスクリプトを挿入する定数。
    • atDocumentEnd:ドキュメントの読み込みが完了した後、他のサブリソースを読み込む前にスクリプトを挿入する定数。
  • 「ほ〜ん・・・」

結論

WKUserScriptでは指定したタイミングでJavaScriptをWebViewに注入することができる。
injectionTimeのパラメータを指定すると「WebViewのドキュメントの読み込みが完了した後」に注入するか「ドキュメントの読み込みが完了する前」に注入するか選択できる。

今回は「WebViewのドキュメントの読み込みが完了した後」にJavaScriptをWebViewに注入していたため、サーバー側でのLocalStorage読み取りタイミングの段階ではLocalStorageに値が設定されていなかったことで発生していた。

原因

WKUserScriptのコードをネット(ChatGPT)から拾ってきて深く考えずに使ったこと。
printデバッグで値が設定されていることを確認できていたため、アプリ側に問題があると真剣に考えていなかったこと。

修正後のコード

injectionTimeのパラメータを.atDocumentStartに変更

.swift
// webViewのローカルストレージにキーを設定
webView.configuration.userContentController.addUserScript(WKUserScript(
    source: "localStorage.setItem('\(localStorageKey)', '\(key)');",
    injectionTime: .atDocumentStart,
    forMainFrameOnly: true
))
0
0
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
0
0