Category: Mobile Development

Loading Offline Resources in WKWebView with a Local Web Server

1. Background

The author mentioned in the article 《WKWebView》 that WKWebView performs network requests in a process independent of the app process, and the requested data does not pass through the main process. Therefore, using NSURLProtocol directly on WKWebView cannot intercept the request. Therefore, if you need to intercept requests, a feasible solution is to use the private API exposed by Apple's open source Webkit2 source code (see section 3 of the original article for details: NSURLProtocol issue).
However, using private API will inevitably bring about the following problems:

  • Audit risk
  • When intercepting http/https, the post request body is lost
  • If ajax hook is used, there may be post header character length limit, Put type request exception, etc.

From this point of view, before the arrival of iOS11 WKURLSchemeHandler [Explore], the private API was not so perfect.
Fortunately, through searching, we found that the iOS system has the ability to build a server, and it is theoretically possible to implement WKWebView offline resource loading.

2. Analysis

Local web server based on iOS currently has the following relatively complete frameworks:

  • CocoaHttpServer (Supports iOS, macOS and various network scenarios)
  • GCDWebServer (based on iOS, does not support https and webSocket)
  • Telegraph (Swift implementation, more complete functions than the above two categories)

Because most APPs currently support ATS, and most domestic project codes are still implemented using OC, this article will conduct experiments based on CocoaHttpSever.
Telegraph was born to supplement the shortcomings of CocoaHttpSever and GCDWebServer. For pure Swift projects, it is recommended to use Telegraph.

Read more…

Adapting to WKWebView

1. Analysis

In iPhone 6s and iOS 10.3.2, make 10 requests to http://www.qq.com and get the following data:

Run UIWebView memory consumption WKWebView memory (app) consumption UIWebView request time-consuming WKWebView request time-consuming
1 67.47 MB 0.81 MB 4.13 s 0.80 s
2 58.23 MB 0.86 MB 1.16 s 0.54 s
3 57.83 MB 0.50 MB 1.14 s 0.56 s
4 59.38 MB 0.88 MB 1.08 s 1.07 s
5 59.70 MB 0.75 MB 1.07 s 0.71 s
6 64.05 MB 0.83 MB 1.47 s 0.65 s
7 59.45 MB 0.81 MB 1.11 s 0.63 s
8 57.55 MB 0.45 MB 1.15 s 0.64 s
9 58.47 MB 0.77 MB 1.17s 0.75 s
10 58.89 MB 0.84 MB 1.11 s 0.70 s

UIWebView average memory consumption: 54.13 MB
WKWebView average (app) memory consumption: 0.75 MB
UIWebView average request time: 1.46 s
WKWebView average request time: 0.7 s

In summary, you can get: The request time of WKWebView is about 50% of that of UIWebView, and it is even better in terms of memory. But in fact WKWebView is a multi-process component, and Network request and UI Rendering are executed in other processes. If you observe carefully, you will find that: when loading, the memory consumption of the App process is very small or even drops significantly, but the memory usage of the Other Process will increase. Therefore: on UIWebView, when the memory usage is too large, App Process will crash; on WKWebView, when the overall memory usage is relatively large, WebContent Process will crash, resulting in a white screen phenomenon.

Read more…