demand
The requirement is to cache the web page locally in case the user has no signal to use it.
perform
So let’s do it. In the past, all I did was interact with the H5 App, transferring data, retrieving events and responding to things like that. Here’s the idea:
- WebView offline cache mechanism, here explained several schemes, but are not implemented, but here learned a lot about webView cache knowledge and scheme, some on UIWebView is ok, but not on WKWebView.
- WKWebView uses the canInitWithRequest method, but the whole process is independent of the NSURLProtocol. The thinking of the great god source is iOS WKWebView (NSURLProtocol) intercept js, CSS, images resources, found using WKBrowsingContextController and registerSchemeForCustomProtocol, Through the reflection to the private class/selector, by take a browsingContextController KVC, registration by the HTTP and HTTPS requests to NSURLProtocol processing. [NSURLProtocol wk_registerScheme:@”http”]; [NSURLProtocol wk_registerScheme:@”https”];
- See here can achieve WKWebView cache, le thoughts, through the way of KVC browsingContextController get private interface, The HTTP and HTTPS when invoking registerSchemeForCustomProtocol also added, so it can intercept the HTTP and HTTPS requests, and then write their own inheritance NSURLProtocol custom class, HTTP (s) requests can be intercepted in canInitWithRequest by rewriting methods such as canInitWithRequest, startLoading, etc. Check local cache data in startLoading. If yes, use and start asynchronous threads to update the cache. If no, download and call NSURLSession to cache the data in NSURLCache.
New problems
A new problem was found. When the web page was opened, it could cache the data it saw, but when it clicked to play a piece of audio or display a picture, it would find that this part of data was not cached. Due to this part of h5 request down only after the click, which means the user must put all of the click event click again to need pictures or audio in accordance with the above approach to the local cache, one thousand users in points, nothing went out, and no net again open web pages detection can only look, click after audio or pictures are can’t use, That’s not what we need.
Here’s what I thought after I finished
- Since WkWebView can’t automatically cache all the data we need, let us download the data that can’t be cached, but how to put local data into the web page?
- Android webView Not allowed to load local resource error solution, his implementation idea is to replace the local path to the web page, However, if the web page is not allowed to load local, it will appear not allowed to load local. This article provides a method for blocking URL replacement resources. I wonder if Apple can also do this.
- But shouldInterceptRequest doesn’t have a method like this. If the request contains the convention field that says to get local data, we need to re-construct WebResourceResponse to pass in the data as streamed.
- Image [0] replaces the local stream with document.image[0] in webView Finish. It does, but it does not replace the image I want to replace. How do I get the path to the image that needs to be replaced, and then give it the resource, also can’t get the JS code, inside the operation?
- The other day, I sorted out the process of WKWebView’s caching mechanism, and found that NSURLProtocol also has a corresponding method, that is, in startloading, it also takes the cache data stream and updates the cache on the web page. If I determine that the intercepted path is a picture, I can replace the local data stream with the original data stream from NSURLCache to update the web page.
- Try it and sure enough, since the image into NSData data stream way can, then audio should also be able to achieve the perfect replacement of data stream, so as to achieve the cache of all data on the web page. Only part of the web page is automatically cached, part of it does not have its own automatic cache, we take the local data stream downloaded by ourselves.