Note that the code and some of the concepts in this post are outdated
This example builds upon the Getting started with WKWebView using Swift in iOS 8 article which explains how to get started with WKWebView, read that one first.
The demo application
To communicate between a web-page and WKWebView we need two main elements.
A WKWebView native application which talks to the web-page
The web-page is really simple. There are two files, one «index.html» file which is the web-page and one «main.js» file which «index.html» includes at the end of its body tag.
When this script loads it will wait 5 seconds and then call the «callNativeApp» method. The only thing to note here is the "callbackHandler". This is the name of the script message handler we will define later in the native application.
Also, I'm wrapping the callback to "webkit.messageHandlers....." in a try catch block to avoid the script falling over when it's running outside of a native app context.
There is also a tiny function which will change the header in the HTML page to a red color when run, well use this later.
You can load this web-page from a server or simply include it in your app. I'll be loading it from a local server to simulate a more realistic example.
The native application
The first thing you need to do is to point the WKWebView we created in the previous article to the new test URL. You'll need to include you own path here. If you're wondering how to set this up please refer to the Getting started with WKWebView using Swift in iOS 8 article this article build upon.
var url = NSURL(string:"http://localhost/WKJSDemo/") var req = NSURLRequest(URL:url) self.webView!.loadRequest(req)
The WKWebView configuration
In «Getting started with WKWebView using Swift in iOS 8» we initialized the WKWebView with no parameters, like so:
self.webView = WKWebView()
This is fine for simply loading a web-page. Now however we want to inject some script into the page and this calls for some additional configuration.
The WKWebView constructor has a «configuration» parameter which takes a
userContentController property of the
userContentController property expects an instance of
WKUserContentController which has a method called
addUserScript. We utilize this method to add the user script. Phew! Let's look at a simple example.
The first thing to do is to create a content controller.
var contentController = WKUserContentController();
Now we need a user script to pass into the addUserScript method of the content controller.
var userScript = WKUserScript( source: "redHeader()", injectionTime: WKUserScriptInjectionTime.AtDocumentEnd, forMainFrameOnly: true ) contentController.addUserScript(userScript)
Great, now we need to create a configuration and then add the contentController to it and pass the configuration into the WebView constructor.
var config = WKWebViewConfiguration() config.userContentController = contentController self.webView = WKWebView( frame: self.containerView.bounds, configuration: config )
Now try to run it, you should see a HTML page with a red header.
Note that the WKWebView constructor requires a "frame" parameter. This tells the web view how big it should be and is very common pattern in UIKit classes.
Adding the delegate method
class ViewController: UIViewController, WKScriptMessageHandler
Here we update the ViewController to include the «WKScriptMessageHandler». This will give you an error, this is because we haven't yet implemented the «userContentController» delegate method. We'll do this now.
contentController.addScriptMessageHandler( self, name: "callbackHandler" )
Try to run it. The header should now be read and after five seconds you should get a message in the Xcode console. Success!
All the code