Dissecting Javascript clicks in UIWebView

In VG we make heavy use of UIWebView, almost all of our iOS apps is a mix between native code and HTML. This is nice and dandy for presenting all sorts of content – being a newspaper means tons of webpages with ads, frames, javascript menus and whatnot.

Generally this works out really well, but for a long time we had a problem with links intercepted by javascript and how to distinguish these from an iframe loading. Why would we want to do this? Sometimes we wish to load linked pages in a separate view, leaving the originating page intact. Clicking on an article on our front page will push a new webview on the navigation stack so that when you’re done reading the article you can close it and instantly go back to the same spot on the front page. We use webview’s shouldStartLoadWithRequest delegate method for this purpose, like this:

 

That’s fine for regular links and forms, but  as soon as you hook up some javascript to your a- tags 

they will be ignorered by our code.

The problem is the navigationType, which has 6 possible values:

When javascript is attached to a link, the navigationType will no longer be reported as UIWebViewNavigationTypeLinkClicked – you will get a UIWebViewNavigationTypeOther instead. So we’ll just check for that! Unfortunately it’s not that easy. Every page load and iframe in your page will trigger this action as well.. How can we separate the javascript-bound links and a regular page load ?

NSURLRequest to the rescue

There are a couple of  methods in NSURLRequest which might seems irrelevant at first, but we’ll use them to serve our purpose.

All iframes loading will have their URL pointing to a specific address, but the mainDocumentURL will still name our original document, in other words, they differ. But what happens when we click on our javascripted links ? The URL and mainDocumentURL will be the same, if they link to a new page. And that’s exactly what we’re interested in. The only problem that remains is the first page load, which happens to follow the same pattern. There are several ways to work around that, but one quick and easy solution is to check for the inital URL and handle that as a special case. Wrapping it all up you can try something like this:

 

 

You still might want to check for other URLs, such as links to Appstore and other apps and let iOS handle those, but your javascript links should now behave nicely. Happy hybrid coding!

Read more from the Software engineering category
SUBSCRIBE TO OUR UPDATES
Menu