iOS
WKWebView
JavaScript
alert dialog
troubleshooting

iOS WKWebView not showing javascript alert dialog

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

When JavaScript calls alert() inside a WKWebView, nothing appears unless the native app supplies the dialog UI. WKWebView deliberately separates web rendering from UIKit presentation, so alerts, confirms, and prompts must be bridged by your view controller.

This catches many developers because the web content looks fine and the JavaScript executes, yet the dialog seems to vanish. In practice, the alert is not broken; the native side just has not been told how to present it.

Why the Alert Does Not Appear

WKWebView separates page rendering from the app's user interface responsibilities. JavaScript can request a dialog, but the web view will not create a native UIAlertController on its own. Instead, it calls a delegate method and waits for your app to decide how to present the dialog.

If no uiDelegate is assigned, the page still runs, but the alert() request is effectively ignored from the user's point of view.

Implement WKUIDelegate

The fix is to set webView.uiDelegate and implement webView(_:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:).

swift
1import UIKit
2import WebKit
3
4final class ViewController: UIViewController, WKUIDelegate {
5    private lazy var webView: WKWebView = {
6        let view = WKWebView(frame: .zero)
7        view.uiDelegate = self
8        return view
9    }()
10
11    override func viewDidLoad() {
12        super.viewDidLoad()
13        view = webView
14
15        let html = """
16        <html>
17          <body>
18            <button onclick=\"alert('Hello from JavaScript')\">Show Alert</button>
19          </body>
20        </html>
21        """
22
23        webView.loadHTMLString(html, baseURL: nil)
24    }
25
26    func webView(
27        _ webView: WKWebView,
28        runJavaScriptAlertPanelWithMessage message: String,
29        initiatedByFrame frame: WKFrameInfo,
30        completionHandler: @escaping () -> Void
31    ) {
32        let alert = UIAlertController(title: "Message", message: message, preferredStyle: .alert)
33        alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in
34            completionHandler()
35        })
36        present(alert, animated: true)
37    }
38}

The important detail is the completionHandler. Call it after the user dismisses the alert. If you forget, the page can remain blocked while waiting for JavaScript execution to continue.

Present on the Active View Controller

The delegate method may still fire correctly while the dialog fails to appear because the presentation context is wrong. If another controller is already being presented, or if your web view controller is not visible yet, present can fail or log a runtime warning.

It is also worth keeping all UIKit presentation on the main thread. WKWebView callbacks normally arrive on the main thread, but if your own code hops across queues before presenting the dialog, you can create intermittent UI bugs that look like web view issues.

Handle confirm() and prompt() Too

If the page also uses confirm() or prompt(), implement the matching delegate methods. The pattern is the same: present native UI, then call the completion handler with the user's response.

swift
1func webView(
2    _ webView: WKWebView,
3    runJavaScriptConfirmPanelWithMessage message: String,
4    initiatedByFrame frame: WKFrameInfo,
5    completionHandler: @escaping (Bool) -> Void
6) {
7    let alert = UIAlertController(title: "Confirm", message: message, preferredStyle: .alert)
8    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
9        completionHandler(false)
10    })
11    alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in
12        completionHandler(true)
13    })
14    present(alert, animated: true)
15}

Handling all three dialog types gives your web content predictable behavior and removes another class of hard-to-debug UI issues.

Check the Presentation Context

A practical debugging step is to confirm two things:

  • 'webView.uiDelegate is assigned before loading the page.'
  • The view controller presenting the alert is currently active and visible.

Test with a Minimal Page

During debugging, load a tiny HTML string with a known alert() call. That removes network issues, page-level JavaScript complexity, and content differences from the equation so you can verify that the native delegate path works by itself before investigating the site content.

Common Pitfalls

  • Setting only navigationDelegate and forgetting uiDelegate. Navigation callbacks do not handle JavaScript dialogs.
  • Forgetting to call the completionHandler, which can leave JavaScript execution waiting indefinitely.
  • Presenting the alert from a controller that is not currently on screen.
  • Testing with a page that suppresses alerts for its own reasons and assuming the native delegate is broken.

Summary

  • 'WKWebView does not show JavaScript alert() dialogs automatically.'
  • Assign a WKUIDelegate and implement the alert delegate method to present native UI.
  • Always call the provided completionHandler after the user responds.
  • Implement the matching confirm and prompt delegate methods if the page uses them.
  • If the delegate is correct and nothing appears, check view-controller presentation state next.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.