WKWebView. My experience

We (iOS developers) use WKWebView since iOS 8, as a replacement for UIWebView. Even it looks pretty simple (load HTML and render it in special view), webViews has problems when working with them.

In this article I want to share some of my thoughts about using WebViews in your iOS project.

Problems

At first sight webView should not be difficult thing. Like render some HTML or load web page by URL. But working with WKWebView in iOS might easily become non trivial task. I tried to divide my experience in 4 sections:

  1. Cookie management
  2. Terminated content process
  3. Memory issues
  4. Info.plist :)

Cookies

When you load page, you load instance of URLRequest in webView. WebView handles it’s cookies by it’s ProcessPool, you don’t need to interrupt it’s work.

To receive HTTP headers and cookies (cookies are one of the HTTP headers) though WKWebView you should implement WKNavigationDelegate method

But you can extract HTTP headers here only on page actually renders. That means that if you have chain of redirects, you can not extract headers from one of them.

HTTP headers extraction

If you want to check webViews cookies at exact moment, than do it though Safari Web Inspector (enable JavaScript debugging in iPhone settings first). HTTPCookieStorage is usually out of sync with Safari.

As I mentioned before, cookies, cache and all of that kind of resources are handled by WKProcessPool instance of webView. If you need to share cookies between different webViews, than share the same process pool in their configurations.

If you really need to inject your own cookies, that do it in two steps.

  1. Set cookies in appropriate header field when you create URLRequest instance
  2. “Inject” your cookies with javascript once page loaded with WKUserScript
Cookie injection scheme

This is how UIViewController with such logic could be

Be careful, when dealing with redirects and mutating cookies. During redirects webView uses it’s internal cookies state, not that you passed at first loading. For example:

  1. You set custom cookies in URLRequest, load it in webView.
  2. WebView receives code 30x (redirect), servers set’s his cookies through headers.
  3. WebView builds new URLRequest based on it’s internal state. Your cookies probably missing hear. Check it with Charles

In conclusion about cookies I would like to recommend you to leave cookie logic to webView, and if you need to track requests from your app by your server, then do it by setting custom user agent. By setting it 
through UserDefaults iOS guarantees you that every HTTP request will have that user agent.

Terminated content process

The web view whose underlying web content process was terminated.

What does it mean for your users? It means “White screen of death”. Your users see no content. Firing “reload” method won’t work. WebViews property URL is set to nil. You should track this event and try to recover your webView, load last known URL or recreate webView.

This event might appears when you load page with difficult JS, or upload huge media (high resolution picture for example).

Memory issues

WKWebView API is not perfect. If you build complex stuff with webView, check for memory leaks.

For example if you want to track listen to JS code, you need to add WKScriptMessageHandler to your WKUserContentController:

But content controller holds strong references to his script message handlers. It means that you will receive a retain cycle, if you set your message handler to WebView it’s self, or your viewController. You should wrap your message handler into weak reference container, like this

And add script message handler like this

Info.plist

If you add WKWebView to your project, than add these keys with descriptions to your info.plist (works on iOS 11), otherwise you will get crashes. I’ve got many of them.

Final thoughts

I won’t say, that any webView is good. I just wanted to share some of my experience, which my help other developers.

If you want to go for cross platform solution, than use Flutter or React Native. Use webView, when you need some prototype in your native app, when you have to render some HTML actually, but don’t make a silver bullet out of it.


This is my first publication, so don’t judge me strictly. Feedback and claps are welcome!