Taming alert() in UIWebView

Calling alert() in UIWebView will give you a popup with your URL (hostname) as the Dialog title, which is very annoying.

argh…

There are few methods discussed here to hack this (http://stackoverflow.com/questions/10681381/change-javascript-alert-dialog-title-in-ios) but they are not very elegant.

With the introduction of JavaScriptCore, we can nicely replace alert function with native function via JSContext.

class ViewController: UIWebViewDelegate {
  let webview: UIWebView!
let alertFunction:@convention(block) String -> Void = { (message) in // #1
UIAlertView(title: "Native Alert", message: message, delegate: nil, cancelButtonTitle: "OK").show()
}
  func viewDidLoad() {
webview.delegate = self
}
  func webViewDidFinishLoad(webView: UIWebView) {  // #2
if (webview.loading) { return } // #3
let context = webview.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") as! JSContext
context.exceptionHandler = { context, exception in
print("JS Error: \(exception)"
}
context.setObject(unsafeBitCast(alertFunction, AnyObject.self), forKeyedSubscript: "alert")
    // test
context.evaluateScript("alert('Test Message');")
  }
}
  1. alertFunction is our native popup function. In this example i use the deprecated UIAlertView to simplify the demo. You should use UIAlertController or your custom popup.
  2. We need to do this each time the page is loaded, so the code goes into UIWebViewDelegate function webViewDidFinishLoad.
  3. Since the webview could be calling webViewDidFinishLoad multiple times (ajax call etc) we make sure the code is executed only once, after webview.loading is true.
alert(‘Test Message’) resulting in a native dialog without the URL as title
One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.