【Swift】WKWebViewでJavaScriptのポップアップが表示されない原因と対応方法
この記事からわかること
- SwiftでWebサイトをiOSアプリから開く方法
- WKWebViewクラスの使い方
- JavaScriptのwindow.alert()/window.confirm()が表示されない原因
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
環境
- Xcode:16.0
- iOS:18.0
- Swift:5.9
- macOS:Sonoma 14.6.1
WKWebViewでJavaScriptのポップアップが表示されない原因
iOSアプリからWebViewでWebページを表示している際にJavaScriptで実装していたalert
とconfirm
が表示されない事象が発生しました。調べてみるとWKWebView
ではデフォルトではポップアップ表示に対応していないようです。
window.alert('Hello, World!')
window.confirm('Hello, World!')
⇧上記でポップアップ出るのでWebViewで開いて確認してみてください。
ポップアップを表示させる方法
WKWebView
でポップアップを表示させるにはWKUIDelegate
のrunJavaScriptAlertPanelWithMessage
とrunJavaScriptConfirmPanelWithMessage
デリゲートメソッドを活用します。
この2つのメソッドではJavaScriptで実装したalert
とconfirm
をネイティブ側のアラートへ繋ぎこむことができるようになります。confirm
で押下した後の処理もcompletionHandler
で返却するBool
値によって制御し、JavaScript側の押下後の実装を問題なく動作させることが可能になっています。
/// JavaScriptのwindow.alert()を処理
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
// ここでネイティブアラートの表示を実装する
let alert = UIAlertController(title: "Alert", message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in
completionHandler()
})
self.present(alert, animated: true, completion: nil)
}
/// JavaScriptのwindow.confirm()を処理
func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
// ここでネイティブアラートの表示を実装する
let alert = UIAlertController(title: "Confirm", message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
completionHandler(false)
})
alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in
completionHandler(true)
})
self.present(alert, animated: true, completion: nil)
}
uiDelegate
プロパティへのセットも忘れずに。
webView.uiDelegate = self
これで無事WebViewからポップアップが表示されるようになりました。
Swift UIで実装する
Swift UIでUIViewRepresentable
を使用している場合は以下のように実装すればアラートが表示されます。
// JavaScriptのwindow.alert()を処理
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
guard let rootViewController = windowScene?.windows.first?.rootViewController else {
completionHandler()
return
}
let alert = UIAlertController(title: "Alert", message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in
completionHandler()
})
DispatchQueue.main.async {
rootViewController.present(alert, animated: true, completion: nil)
}
}
// JavaScriptのwindow.confirm()を処理
func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
guard let rootViewController = windowScene?.windows.first?.rootViewController else {
completionHandler(false)
return
}
let alert = UIAlertController(title: "Confirm", message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
completionHandler(false)
})
alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in
completionHandler(true)
})
DispatchQueue.main.async {
rootViewController.present(alert, animated: true, completion: nil)
}
}
AndroidのWebViewでも同じです
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。