Enable zoom for web pages on UIWebView - Swift

Yesterday I ran into annoying problem. In one of our apps we load web pages in standard UIWebView. Nothing great, everyone does it. However, the requirement was user should be able to pinch and zoom them since the font was too small for an ordinary user. It was totally fine until this point. Since I can simply turn on scalesPageToFit property on the UIWebView and then it will shrink it to fit the screen size and then user can pinch and zoom to get detailed info.

However, for some of the web pages following property was mentioned in the header meta tag which prevented pinch and zoom behavior by default.


<meta name="viewport" content="width=device-width, user-scalable=0" />

Here user-scalable property is important. Since the value is set to 0, it won't allow user to scale page anymore which prevents pinch and zoom behavior.

In order to do it, I had to modify this header dynamically through JavaScript DOM manipulation.
This is how I did it.


func webViewDidFinishLoad(webView: UIWebView) {
	self.webView.scrollView.minimumZoomScale = 1.0
	self.webView.scrollView.maximumZoomScale = 5.0                                  
    self.webView.stringByEvaluatingJavaScriptFromString("document.querySelector('meta[name=viewport]').setAttribute('content', 'user-scalable = 1;', false); ")
}

UIWebView has a delegate method which is called as soon as the web page loading operation is completed.

Make sure you modify DOM after web page loading is completed. If you try to do it before it, it will be overridden by default rule in specified on the web page. Manipulating DOM after page load ensures that our manual manipulation will trump any other previously set rule.

Sometime when you manipulate DOM at the end of page load, there is slight flicker when page tries to scale itself to fit the given scale. If you think this is the problem, you can set alpha=0 initially when you are about to load it and then once loading completed, you can change alpha=1 with animation. This will make sure abrupt scaling operation at the end won't be obvious to user.:

It can be done as follows after you finish manipulating DOM :

UIView.animateWithDuration(0.25) { () -> Void in
    self.webView.alpha = 1.0
}

Before you do this, please make sure to set alpha = 0 in webViewDidStartLoad method when web view is about to load the URL content

func webViewDidStartLoad(webView: UIWebView) {
    self.webView.alpha = 0.0
}