Javascript call to Swift from UIWebView

You must a custom URL Scheme such as myawesomeapp and intercept requests to it using:

func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool

Fire a call to native code using window.location=myawesomeapp://hello=world, and get the query params you pass from request.URL.query in the native code.

For more information, see my question about UIWebViews here: JavaScript synchronous native communication to WKWebView


I would suggest looking into using WKWebView instead UIWebView. You then won't need to register custom URL scheme. Additionally, UIWebView is obsolete and WKWebView has a lot of advantages, most notably performance and rendering as it runs in a separate process.

Link to Apple documentation and recommendation to use WKWebView https://developer.apple.com/reference/webkit/wkwebview/

Important

Starting in iOS 8.0 and OS X 10.10, use WKWebView to add web content to your > app. Do not use UIWebView or WebView.

That said, it's very simple to setup a native to javascript bridge:

import WebKit

class ViewController: UIViewController, WKScriptMessageHandler {
   var webView: WKWebView?
    override func loadView() {
        super.loadView()
        
        webView = WKWebView(frame: self.view.frame)
        webView?.configuration.userContentController.add(self, name: "scriptHandler")
        
        self.view.addSubview(webView!)
    }
    
    public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        print("Message received: \(message.name) with body: \(message.body)")
    }
// rest of code
}

Then in your javascript code, call it:

window.webkit.messageHandlers["scriptHandler"].postMessage("hello");

I have written a library that leverages this and adds some fancy javascript syntax. https://github.com/tmarkovski/BridgeCommander

To use it, just reference the project (or add the swift and javascript files to your Xcode project) and call

    webView = WKWebView(frame: self.view.frame)
    let commander = SwiftBridgeCommander(webView!)
    
    commander.add("echo") {
        command in
        command.send(args: "You said: \(command.args)")
    }

You then will be able to use callback syntax in javascript like this

var commander = new SwiftBridgeCommander();
commander.call("echo", "Hello", function(args) {
        // success callback
    }, function(error) { 
        // error callback
});