How to use JSContext from JavaScriptCore to create two way communication with web page

What is “JavaScriptCore”? Well, it is a name for internal Safari javascript engine. Is it useful? For most of us it is not, but if you thinking about communicating between your Swift app and web page, it can be really useful.

The problem is simple if you just want to fire some actions if button or link is clicked. Just add “#myaction” in url, then you can easily capture URL change. More complex question is – how web page can fire such action in the way which can both iOS and Android use? On Android URL change event works different so that solution is useless. But those guys can capture native js calls like:

Can we (iOS guys) also capture such calls? Not without JavaScriptCore and its JSContext.

Lets start with creating UIWebView, UITextField and connecting them to proper methods. If you don’t have time for this, feel free to grab demo project from github.

After initial work your code should be like this:

Next, we need to add support for UIWebViewDelegate and use webViewDidFinishLoad method, inside which we will create our JSContext. Also don’t forget about importing JavaScriptCore module and load our sample page.

What happens here? In viewDidLoad method nothing special, we’re just loading our web.html page (included on github) into webview. More happens inside webViewDidFinishLoad – here we are creating our JSContext from special javascript object available only on Safari.

Next part is our communication class and protocol. You have to extend JSExport protocol, create your methods and then create your handler class implementing that protocol. Here goes example:

Your ads will be inserted here by

Easy Plugin for AdSense.

Please go to the plugin admin page to
Paste your ad code OR
Suppress this ad slot.

Now important part, in our webViewDidFinishLoad method, add:

This is key to everything. On our JS context we are injecting our CommunicationClass available as “SwiftBridge” in javascript. This will allow webpage to call:

Of course you can name your class whatever you like. Now just run your project, and when you click link in webview, you should see in XCode console something like:
Native function called hi from web!

But wait, there is more! You can also inject blocks instead of object if you want:

If you find this usefull, just spread the word. Share on social. On github you can see also how to call JS functions from Swift, you can enter some text in web text input, and native textfield will reflect changes, also you can enter text in native control and web will show same.

Note: Project was created on XCode 8.2.1 and Swift 3.0.

Leave a Reply