At Embrace, we help mobile companies solve their most difficult production issues. A somewhat common source of bugs is improper management of WKWebView on iOS. The problem is that webviews are incredibly heavy objects from a resource standpoint. Loading too many and failing to properly deallocate them can lead to stutters, freezes, and system crashes for exceeding memory limits.
In this post, we’ll cover the following:
- Why WKWebView is so heavy
- Common ways that developers leak WKWebViews
- How you can find memory leaks when dealing with WKWebView
- Best practices when working with WKWebView
Why WKWebView is so heavy
Before we dive in, we’ve previously covered webviews in our pieces about blank webviews stemming from a terminated content process and blank webviews caused by downgrading. Those are great to check out if you’re struggling to solve blank webviews.
This post will focus on problems stemming from loading and retaining too many webviews in your app. Webviews are one of the heaviest objects you can allocate. You are basically launching another application within your mobile app and adding two additional processes — a content process and a networking process.
So if your application has one webview in it, your application is actually running on three operating system processes: the application process, the web content process, and the web networking process.
Two webviews means you have five processes.
Three webviews means you have seven processes.
There are no economies of scale when instantiating multiples. In fact, the opposite is true. The more webviews you create, the more sluggish your app will run.
Common ways that developers leak WKWebViews
The most common way to leak WKWebViews is to allocate new ones instead of reusing ones that you’ve already created. Sometimes, engineers think they are properly reusing webviews, but they do not check for buildups of WKWebView instances when profiling in Xcode. Because WKWebView comes from an Apple system library, it’s easy for engineers to not even look beyond their code when debugging a performance issue.
For example, let’s say you have a carousel that loads a webview whenever the user swipes. Some examples are the following:
- Loading an article from a newspaper/magazine app
- Loading a product page from a e-commerce app
- Loading a video from a streaming app
For carousels, you should never have more than two WKWebViews in memory. You should have the current one that the user is looking at, and you should have the next one. But once the user swipes to the next one, you should clear the contents of the first webview and reuse it for the next instance of the carousel. In this way, you can reuse the same two WKWebViews no matter how many times the user swipes through your app.
For scrollviews, there could be more than one WKWebView visible on the screen at a given time. In this case, the maximum number of webviews is however many are required to fill the screen plus one additional one to preload the next webview.
Another way to leak webviews is to keep broken ones around instead of deallocating them. Whenever a user faces a blank webview, you should have code that determines whether it should be reloaded or removed. For example, if your checkout page is served from a webview, you will want to reload it. If the broken webview was serving an ad, you might want to remove the webview, since you might not be able to fix it.
How you can find memory leaks when dealing with WKWebView
You can identify memory leaks through the Xcode memory graph. When debugging with Xcode, if you navigate to the areas in your app that have webviews, you can see the number of WKWebViews that are in memory at a given time by expanding the left section. You can swipe through carousels or navigate scrollviews to see if the number of webviews in memory increases.
Best practices when working with WKWebView
The first best practice is to limit the number of WKWebViews in your mobile applications. One of the heaviest actions you can take in an iOS app is to create a new WKWebView. They take up a lot of memory and add additional processes. Wherever it makes sense to do so, consider converting webviews into the corresponding native functionality.
The second best practice is to reuse WKWebViews instead of creating new ones. You can clear old content and load new content into an existing WKWebView instance ad nauseam, and this will be much better performance-wise than deleting and creating entire webviews.
The third best practice is to write appropriate tests to flag leaking webviews. And you can be aggressive here. If your webviews only appear in a carousel, then you know you never need more than two in memory at a given time. Write a test that fails if more than two webviews appear.
Likewise, if you have webviews as product listings in a scrollview, you can calculate the maximum number of webviews that your app should ever need to have in memory. The same testing methodology as before applies here.
Summing it all up
Stutters and slowdowns in iOS applications that use WKWebView can easily stem from creating too many webviews and not being efficient with their reuse. It’s important to leverage Xcode’s memory graph and appropriate tests to uncover leaks in your webviews so you can deliver better performance in your mobile apps.
What can Embrace do for your team today?
Embrace is a data driven toolset to help mobile engineers build better experiences. We are a comprehensive solution that fully reproduces every user experience from every single session. Your team gets the data it needs to proactively identify, prioritize, and solve any issue that’s costing you users or revenue.
Want to see how Embrace can help your team grow your mobile applications with best-in-class tooling and world-class support? Sign up for a free trial and see how we help teams set and exceed the KPIs that matter for their business!
Deliver incredible mobile experiences with Embrace.
Get started today with 1 million free user sessions.Get started free