WKWebViewのリダイレクト時の挙動

WKWebViewのリダイレクト周りの挙動が分からなかったので調べてみました。 (iOS10 / iOS9) (Swift3.2)

リダイレクトはWKNavigationDelegateで検知するしかなさそう

自分の実験の中ではWKWebViewではリダイレクトのステータスコード(300系)を観測できなかった。 どうやらWKWebViewが内部的にリダイレクトは処理してしまっているようだったので、 WKNavigationDelegateによってそのリダイレクトによる遷移を検知した。

主要なWKNavigationDelegateのメソッド

func webView(WKWebView, decidePolicyFor: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void)

Decides whether to allow or cancel a navigation.

  • リクエストを開始するときに呼ばれる。そのまま遷移をさせるか、キャンセルするかを決める。
  • リダイレクトが起これば連続してよばれる。
  • navigationTypeを見るとクリックよる遷移か、リダイレクトによる遷移かがわかる。

func webView(WKWebView, decidePolicyFor: WKNavigationResponse, decisionHandler: (WKNavigationResponsePolicy) -> Void)

Decides whether to allow or cancel a navigation after its response is known.

  • レスポンスヘッダが返ってきたときに呼ばれる。そのまま遷移をさせるか、キャンセルするかを決める。
  • このあとにリダイレクトでまたnavigationActionが呼ばれることもあるので、ここで終わりとは限らない。

func webView(WKWebView, didCommit: WKNavigation!)

Called when the web view begins to receive web content.

  • リダイレクトが終わってコンテンツのロードが始まった時に呼ばれる。

リダイレクトの流れ

リダイレクトが終わるまで

webView(WKWebView, decidePolicyFor: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void)

webView(WKWebView, decidePolicyFor: WKNavigationResponse, decisionHandler: (WKNavigationResponsePolicy) -> Void)

連続で呼ばれ続け、

リダイレクトが終わってコンテンツのロードが始まると

webView(WKWebView, didCommit: WKNavigation!)が呼ばれる。

気をつけること

  • decidePolicyFor: WKNavigationResponseが呼ばれても終わりとは限らない。さらにそのままdecidePolicyFor: WKNavigationActionが呼ばれることがあり、didCommitが呼ばれるまで終わりとは限らないので気をつける。
  • didCommitが呼ばれて初めてリダイレクトが終了したとわかるが、Webコンテンツのロードが始まらない限り最後のURLがわからない。

P.S.

その他のWKNavigationDelegateのメソッド

didStartProvisionalNavigationdidReceiveServerRedirectForProvisionalNavigationは呼ばれない事もあったのでよく分かっていない・・・

func webView(WKWebView, didStartProvisionalNavigation: WKNavigation!)

Called when web content begins to load in a web view.

これが呼ばれるとリダイレクトがおわりURLが決定しているようだった。これのあとに最後のリクエストかレスポンスがきた。

これのあとにリクエストが来た場合はそれが最後のリダイレクトなのか、そのあとにdidReceiveServerRedirectForProvisionalNavigationが呼ばれ、レスポンスヘッダがきた。

※ なぜか、呼ばれないこともあった…

func webView(WKWebView, didReceiveServerRedirectForProvisionalNavigation: WKNavigation!)

Called when a web view receives a server redirect.

リダイレクトされたときの最後のリクエストのあとで呼ばれ、そのあとにレスポンスがきた。

※ なぜか呼ばれないこともあった…