WKWebView で target = _blank と POST の組み合わせ注意

target = _blank かつ POST リクエストの際に画面が表示されないバグを出してしまったので気をつけないといけない。

WKWebViewでtarget="_blank"なリンクが開かない時の対処法 - Qiita のコメント欄で注意喚起がされている。

target="_blank" を強引にメインのwebViewにロードさせる場合は注意が必要です。
例えばイベントサイトのATNDで参加登録をした時、
メインフレームで参加登録リクエストが投げられ、別ウィンドウでTwitterへの投稿画面が開かれようとします。
このとき、別ウィンドウで開かれようとしているTwitterへの投稿画面を、
参加登録リクエストを送信するはずだったwebViewに読み込ませてしまうと、
肝心の参加登録処理が実行されないままになってしまいます。

つまりどういうこと?

注意1. target = _blank

WKWebView で target = _blank を開くことができないので、下記のように自力で load request を送る必要がある。

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    guard navigationAction.targetFrame else {
        webView.load(URLRequest(url: url))
        decisionHandler(.cancel)
        return
    }
    decisionHandler(.allow)
}

注意2. WKWebView で POST パラメータが空っぽ

webView.load(URLRequest(url: url)) では POST のパラメータが消えてしまう。
実際に iOS Simulator + Safari Debug で確認した。

これをアプリ側でどうにかするためには、

  1. request が POST か判定
  2. POST だったらネイティブ側で Request を発行し HTML を取得 (API を叩く感じ)
  3. その返り値を WKWebView にセットする

つらい。

参考: WKWebViewでNSURLRequestをPOSTするとヘッダーが消える問題(解決) « TORQUES LABS

なので

  • 社内サービスで調整できる場合
    • Web の人に iOS でアクセスきた時は target = _blank 外してくれという話をする
  • 社外サービスでどうしようもない時
    • がんばってネイティブ側で HTML 取得する

という対策をとる必要がある。

そもそも

アプリで WebView を使うのやめようぜ!!!!!!!!!!!!!!!!!!!