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.