How to run native code from a WKWebView


You’re more of a video kind of person? I’ve got you covered! Here’s a video with the same content than this article 🍿


Did you know that the code of the iOS Wikipedia app is open source and available for anyone curious to learn about the inner workings of this app?

A few weeks ago, I decided to spend 2 hours to explore this code base, because I had a feeling that I could maybe learn something valuable.

I’m pleased to report that I indeed did learn something very interesting, and that’s what I want to share with you in this article!

When you’re exploring such a massive code base, you need to focus on something specific, otherwise you’ll just end up brushing the surface.

So I decided to focus on one of the core screens of the app: the screen that displays the content of a Wikipedia article.

As you can see, this screens allows the user to read the entire content of the article and lets them interact with it:

  • tapping on a link to another article triggers a push navigation

  • tapping on an image displays a new screen modally

  • tapping on a footnote displays its detail and updates the nav bar

On the surface, my feeling was that this screen must had been implemented using either a single UITextView or through a UICollectionView that contains several UILabel.

But when I used Xcode’s debugging tool to capture the view hierarchy, I was really surprised to see that it was actually powered by a WKWebView!

As an iOS developer that believes strongly in native apps, you can guess that I’m, of course, not the biggest fan of web views.

So seeing a web view being used to implement the core feature of a popular app was quite unexpected and unsettling!

But thinking about it, this choice actually makes a lot of sense: Wikipedia is first and foremost a website and its content was created to be displayed using HTML and CSS.

Taking that into consideration, it does make sense for the Wikipedia app to use a web view to render its content, rather than to spend precious time and energy trying to reproduce the exact same look and feel using iOS native components.

However this doesn’t explain one thing: how on earth is this web view able to trigger a native navigation in response to user interaction?

This is actually implemented using a very powerful not but not very well known API introduced by Apple with iOS 8 and called WKScriptMessageHandler.

What this API does is to provide the JavaScript code running inside a web view with a special function that, when called, will trigger native code in the app that embeds the web view.

Here’s how it works:

1. the app creates a bridge to receive messages from the web view

2. the user taps on a link in the web view

3. JavaScript code in the web view calls the function webkit.messageHandlers.bridge.postMessage(message)

4. the web view forwards the message to its userContentController

5. the userContentController parses the content of the message

6. native code is executed to run the action that corresponds to how the user interacted with the app

And this is how tapping on a link in a web view results in a new view controller being pushed onto the navigation stack 🙌


You see, I definitely wasn’t lying when I claimed that you could learn some really cool tricks just by spending a couple hours exploring the open source code base of a popular iOS app!

So if you have the time, I would really recommend that you also give it a try and start exploring an open source code base: I’m sure that you’ll learn something useful along the way 👨🏻‍🎓👩🏽‍🎓

You can find detailed lists of open source iOS apps here and here.

Previous
Previous

5 very useful functions from Swift Algorithms

Next
Next

AI features in Xcode 16: is it good?