Swift, WKWebView

WKWebview: Advanced

If you are new to WKWebview, checkout the WKWebview: Getting Started guide for basics on WKWebview

In this week, we take a look at some of the advanced configuration and functions that WKWebview offers. We continue with the ExampleViewController from the basics article and add some more functionalies to the webview . Currently the loadWebview function for loading local HTML file looks like this,

func loadWebview() {
    webView = WKWebView()
    let htmlFileURL = Bundle.main.url(forResource: "index", withExtension:"html", subdirectory: "public", localization: nil)!
    let parentURL = URL(string: (htmlFileURL.absoluteString as NSString).deletingLastPathComponent)!
    webView.loadFileURL(htmlFileURL, allowingReadAccessTo: parentURL)
    self.view = webView
}

WKScriptMessageHandler

For adding various configuration and properties to the WKWebView we have to use the WKWebViewConfiguration object provided in WebKit . This can be used to configure the web cookies, URL schemes, handling of media content, custom scripts and custom rules.

For now, we shall use this to add an observer to listen and try to communicate with the Javascript. The messages passed between native swift code and javascript is called a Script Message and type is of WKScriptMessage . Now let us add one script message handler to our webview.

let wvconfiguration = WKWebViewConfiguration()
wvconfiguration.userContentController.add(self, name: "messageFromJavaScript")

First we create a WKWebViewConfiguration object and then we add script message handler to the userContentController property. userContentController is the object that coordinates this communication between native code and webpage scripts.

We add the self to be the listener for the messages and we name the message handler as messageFromJavaScript . This name will be used in JavaScript while sending messages which we shall see shortly. The function will now look like this

func loadWebview() {
    webView = WKWebView()
    let htmlFileURL = Bundle.main.url(forResource: "index", withExtension:"html", subdirectory: "public", localization: nil)!
    let parentURL = URL(string: (htmlFileURL.absoluteString as NSString).deletingLastPathComponent)!
    let wvconfiguration = WKWebViewConfiguration()
		wvconfiguration.userContentController.add(self, name: "messageFromJavaScript")
		webView.loadFileURL(htmlFileURL, allowingReadAccessTo: parentURL)
    self.view = webView
}

In order to set self as the message listener it should conform to WKScriptMessageHandler protocol.

class ExampleViewController: UIViewController, WKScriptMessageHandler {

Now the compiler will throw an error saying “does not conform to protocol ‘WKScriptMessageHandler’ “. This means that we are saying that ExampleViewController is capable of handling script messages but we have not added any function to handle those messages in our view controller. Click fix or add this code inside the ExampleViewController

func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
		
}

This is the delegate method that WKScriptMessageHandler provides for us to handle the script messages. Inside this we shall receive our message and process them.

As you can see, the function argument contains message which is of type WKScriptMessage .

func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    if message.name == "messageFromJavaScript" {
        let js = "document.getElementById('my-div').innerHTML='Hello World';"
        webView.evaluateJavaScript(js, completionHandler: nil)
    }
}

We check if the name is messageFromJavaScript and then set the div’s content as “Hello World”.

evaluateJavaScript is a function that is used to execute a Javascript statement. Using this we set the content to “Hello World”.

If any JSON data is passed we can access that using message.body as! [String:Any] and use them inside to carry out some task.

That wraps up this week’s article. I hope this gave you an insight on how to communicate between native code and webpage scripts.