WKWebViewでJavaScriptのalertconfirmpromptを表示する方法です。

参考にしている情報は、以下の3つです。

完成形

完成のイメージは以下のとおりです。

Alert コンソール 動作
OKしか表示しない。返り値はundefined。
Confirm コンソール 動作
OKをタップするとtrue、キャンセルをタップするとfalseが返る。
Prompt コンソール 動作
OKをタップすると、TextViewに入力した値が返ってくる。キャンセルのときはnullが返る。第2引数にデフォルト値を入れると、TextViewの初期値としてセットされる。

実装方法

JavaScriptを有効にする

まずは、WebViewのJavaScript実行を有効にしておきます。 WKWebViewConfigurationを介してセットします。

let webPagePreference = WKWebpagePreferences()
let preferences = WKPreferences()
if #available(iOS 14.0, *) {
    webPagePreference.allowsContentJavaScript = true
} else {
    preferences.javaScriptEnabled = true
}

let configuration = WKWebViewConfiguration()
configuration.defaultWebpagePreferences = webPagePreference
configuration.preferences = preferences

webView = WKWebView(frame: .zero, configuration: configuration)
view.addSubview(webView)

WKUIDelegateを実装する

WKUIDelegateの3つのメソッドを実装します。

extension MyWebViewViewController: WKUIDelegate {
    // `alert` を表示する
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
        alert.addAction(.init(title: "OK", style: .default, handler: { _ in
            completionHandler()
        }))
        present(alert, animated: true, completion: nil)
    }

    // `confirm` を表示する
    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
        let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
        alert.addAction(.init(title: "OK", style: .default, handler: { _ in
            completionHandler(true)
        }))
        alert.addAction(.init(title: "キャンセル", style: .cancel, handler: { _ in
            completionHandler(false)
        }))
        present(alert, animated: true, completion: nil)
    }

    // `prompt` を表示する
    func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
        let alert = UIAlertController(title: nil, message: prompt, preferredStyle: .alert)
        alert.addTextField { textField in
            textField.text = defaultText
        }
        alert.addAction(.init(title: "OK", style: .default, handler: { _ in
            completionHandler(alert.textFields?.first?.text)
        }))
        alert.addAction(.init(title: "キャンセル", style: .cancel, handler: { _ in
            completionHandler(nil)
        }))
        present(alert, animated: true, completion: nil)
    }
}

これで、表示の実装は完了

WKUIDelegateをWKWebViewにわたす

最後に、WKWebViewのインスタンスに、WKUIDelegateを渡します。

webView.uiDelegate = self  // selfにUIDelegateの実装がされている場合

これで完成!