A, WKWebView

1. Introduction

WKWebView is the core control of WebKit launched by apple when it released iOS 8 at WWDC2014. It is a new H5 container and can be used to replace UIWebVeiw. Compared with UIWebView, it has faster loading speed and performance, and lower memory footprint; Refactoring UIWebViewDelegate and UIWebView into 14 classes and 3 protocols allows developers to do more detailed configuration.

2. Advantages and disadvantages of WKWebView compared with UIWebView

Advantage:

  • It has a much lower memory footprint it’s about a quarter of the memory footprint of UIWebView
  • More support for HTML5 features
  • Up to 60fps scrolling refresh rate and built-in gestures
  • Same JavaScript engine as Safari
  • Listen through KVOEstimatedProgress, the loading progress can be obtained(UIWebView calls private APIS)
  • Listen on the title property through KVO to set the navigation bar title
  • New WKWebViewConfiguration class to implement JS call OC (UIWebView using JavaScript Core)
  • Added the customUserAgent property to customize the UserAgent

Disadvantage:

WKWebView ignores default network storage, such as NSURLCache, NSHTTPCookieStorage, and NSCredentialStorage. WKWebView has its own process, as well as its own storage space for storing cookies and Cache. Other network classes such as NSURLConnection are not accessible and do not support caching. WKWebView’s Cookie management will not be synchronized to NSHTTPCookieStorage. Cookies need to be manually injected to achieve Cookie sharing

3. Basic use of WKWebView



Overview of the WKWebView framework

Here only say some more important use, specific reference: reference link 1: WebKit framework analysis, reference link 2: iOS advanced WKWebView.

(1) An important property WKWebViewConfiguration:

  • Web page rendering and display can be configured through WKWebViewConfiguration.
  • WKUserContentController, WKUserScript,- (void)addUserScript:(WKUserScript *)userScript Add a piece of JAVASCRIPT code to the web page manually (you can also inject cookies into the webView this way)
  • WKWebViewConfiguration uses the WKUserContentController, WKScriptMessageHandler protocol, Implement JavaScript calls to OC (all JavaScript below is replaced with JS). The steps are as follows:
    • Register JS methods:
      • [userContentController addScriptMessageHandler:self  name:@"sayhello"];Copy the code

        Implement the agent method in WKScriptMessageHandler protocol, and execute the corresponding method according to the judgment of the name attribute of message

      • - (void)userContentController: (WKUserContentController *) userContentController didReceiveScriptMessage:(WKScriptMessage *)messageCopy the code

    • Dealloc removes the registration:
      • [userContentController removeScriptMessageHandlerForName:@"sayhello"];Copy the code

        (2) Three important agents:

  • WKNavigationDelegate
    • Tracking the loading process
      • Start loading
        • - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigationCopy the code
      • Began to return to the
        • - (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigationCopy the code
      • loaded
        • - (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigationCopy the code
      • Load failed
        • - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)errorCopy the code
  • Jump to a page
    • Called after receiving a redirect request
      • - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation*)navigationCopy the code
    • After receiving the request, decide whether to jump
      • - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandlerCopy the code
    • Before sending a request, decide whether to redirect
      • - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandlerCopy the code
  • WKUIDelegate
    • Create a new WebView
      • Create a new WKWebview
        • - (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration*)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures*)windowFeatures;Copy the code
    • Prompt box: The three prompt boxes (warning, confirmation, and input) on the Web interface correspond to three proxy methods respectively.
      • The warning box is displayed:
        • - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandlerCopy the code
      • A confirmation box is displayed:
        • - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandlerCopy the code
      • The input box is displayed:
        • - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullableresult))completionHandlerCopy the code
      • Note: when h5 calls js.alert(), UIWebView will directly pop up the alert. WKWebview needs to implement these proxy methods to pop up the alert properly.
  • WKScriptMessageHandler agreement
    • Interaction between JS and Native This protocol contains a method that must be implemented. This method is the key to the interaction between Native and the Web side. It can directly convert the RECEIVED JS scripts into OC or Swift objects.
    • - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;Copy the code

(3) WKWebView processing and JS interaction problems:

  • OC calls JS:
    • Direct call
      • - (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id result, NSError * _Nullable error))completionHandler; Copy the code

        This method returns the result asynchronously through a block. Solve the UIWebView stringByEvaluatingJavaScriptFromString this method returns a value can only be used string, can’t catch the wrong questions.

  • JS call OC:
    • Method 1: WKWebViewConfiguration executes the OC method in the protocol method by using WKUserContentController and WKScriptMessageHandler protocols.
    • Mode 2: when H5 calls js.alert(), the proxy method under the WKUIDelegate protocol of WKWebView will be invoked to display the prompt box.
    • Three: using a third-party framework WKWebViewJavascriptBridge JS and the interaction between the Native.

4. Cookie correlation of WKWebView

Why is Cookie singled out? When we use UIWebView, we don’t use cookies
We just need to write one way to go
HTTPCookieStorageInject one of our users into it
HTTPCookie That’s it. Same application, different
UIWebView Between the Cookie
It’s automatically synchronized. And can be accessed by other network classes for example
NSURLConnection,
AFNetworking.
Due to theWKWebView ignores default network storage, such as NSURLCache, NSHTTPCookieStorage, and NSCredentialStorage. NSHTTPCookieStorage does not actively store cookies, network classes cannot access WKWebView’s own managed cookies, There is also no way to fetch cookies from NSHTTPCookieStorage for WKWebView requests. So when WKWebView needs to initiate a network request, we need to manually inject cookies. Store the cookie information in NSHTTPCookieStorage, and then get the cookie from NSHTTPCookieStorage at the appropriate time to inject WKWebView. Here are some specific questions: What is the client’s current Cookie injection scheme? What kind of problems have been solved? Why use NSHTTPCookieStorage to access cookies if you can’t share cookies in NSHTTPCookieStorage?

  • What is the client’s current Cookie injection scheme? What kind of problems have been solved?
    • Scheme 1: WKWebView initiates a network request to inject cookies into the request header, which solves the problem that cookies cannot be obtained for the first time
    • Scheme 2: In WKWebView WKNavigationDelegate agent method decidePolicyForNavigationAction intercepting network requests to the request header into the Cookie into the Cookie, Solved the problem that cookies could not be brought to a new page
    • Solution 3: In WKWebView WKNavigationDelegate agent method decidePolicyForNavigationAction intercepting network requests into the Cookie, solved the Cookie content change, open a new page Returns the problem that the Cookie of the parent page is not updated
    • Summary: After testing scheme 3, the problem that scheme 2 can solve at the same time can be solved, so the client’s current Cookie injection scheme is the same as scheme 1 and Scheme 3
    • In iOS UIWebView and WKWebView, JavaScript and OC interaction, Cookie management look at me enough, reference link two :【 Tencent Bugly dry products sharing 】WKWebView those pits
  • Why use NSHTTPCookieStorage to access cookies if you can’t share cookies in NSHTTPCookieStorage?
    • Apple provides two classes NSHTTPCookieStorage and NSHTTPCookie to store cookies.
    • Cookie information is not only limited to WKWebView network request, some native page network request also need cookie information, and network classNSURLConnection,AFNetworking, for example, accesses NSHTTPCookieStorage to get Cookie information.
    • If Cookie information is stored in other ways, we have to manage not only WKWebView’s cookies, but also whether non-WKWebView web requests can get cookies.

2. The use of WKWebViewJavascriptBridge

The implementation process of WebViewJavascriptBridge is to save a mutual call information in OC environment and JS environment respectively (can be understood as method name and method implementation). There is an Id and CallBackId between each call to find the corresponding processing for the two environments.

1. WebViewJavascriptBridge framework important class:

  • WebViewJavascriptBridge_JS: Initializes and handles the bridge of the JS environment, which receives messages from OC to JS and sends messages from JS environment to OC.
  • WKWebViewJavascriptBridge: mainly responsible for OC message processing environment, and the OC message is sent to JS environment.
  • WebViewJavascriptBridgeBase:The bridge initialization of OC environment and the encapsulation of messages interacting with JS are mainly implemented.

2. Message processing process of OC environment:

(1) WKWebViewJavascriptBridge open log convenient debugging

(2) Initializing the bridge does a few things:

  • Initializes the Bridge object
  • Make the webView a navigationDelegate as a member variable
  • Initialization WebViewJavascriptBridgeBase object, become the delegate for processing logic interaction of transfer, etc

(3) OC environment registration method for JS call

  • Is registered, with the WebViewJavascriptBridgeBase WebViewJavascriptBridgeBase object to this method to the method name: Handlers are stored in messageHandlers, which execute navigationDelegate methods when they receive a message from the JS side and execute them from messageHander.

(4) Initialize the Web environment (we don’t need to do this)

(5) OC sends a message to JS to invoke the method registered by JS

(6) When JS sends a message to WebView, this proxy method is called back, and the intercepted URL is judged to be the URL type and processed accordingly. This is the basic process of OC and JS interaction in OC environment. For details, see GitHub WebViewJavascriptBridge. Objective C and JavaScript interact with each other

  • Proxy method:  - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandlerCopy the code
  • Intercepted URL type correlation discriminant method
methods

role

-(BOOL)isCorrectProcotocolScheme:(NSURL*)url

Determine whether WKWebViewJavascriptBridge sending or receiving the news of the URL

-(BOOL)isBridgeLoadedURL:(NSURL*)url

Is a bridge message that initializes the JavaScript environment

-(BOOL)isQueueMessageURL:(NSURL*)url

Whether WKWebViewJavascriptBridge sent messages

-(void)logUnkownMessage:(NSURL*)url

Unknown message type
  • Processing logic: whether WKWebViewJavascriptBridge receive or send message URL / _base isCorrectProcotocolScheme: URL]
    • —-> https://__bridge_loaded__ [_base isBridgeLoadedURL:url]
      • Yes: Initializes the BRIDGE of the JS environment.
      • No: to determine whether WKWebViewJavascriptBridge message from [_base isQueueMessageURL: url]
        • Is to call[self WKFlushMessageQueue];Methods. And then by callingWebViewJavascriptBridge._fetchQueue()To get the callback information from JS to OC. The [_base flushMessageQueue:result] method is called to send the callback message from the OC to the OC.
        • No [_base logUnkownMessage: URL] is called to print unknown messages.
    • No: It is not a JS interaction request and is processed as a normal network request.

3. WKWebViewJavascriptBridge pit:

Due to strong reference for _webViewDelegate key in the source code below, so use WKWebViewJavascriptBridge will inevitably lead to a circular reference.




Original solution:



This solution is WKWebViewJavaScriptBridge circular reference the simplest treatment method. However, this can lead to problems where the network request goes to another page without data, and when the data is loaded and returned to the previous page, the proxy method fails. The solution is to identify the source of the controller through the isBeingDismiss method of the controller and break the circular reference when the controller is about to be destroyed. The diagram below:



A summary of WKWebView caches can be found in the next blog WKWebView Cache summary.

Iii. Summary of reference links

  • WKWebView principle use related:
    • WKWebView official document
    • Refer to link 1: WebKit framework analysis
    • Reference link 2: iOS advanced WKWebView



  • WKWebView Cookie
    • Reference link 1: iOS UIWebView and WKWebView, JavaScript and OC interaction, Cookie management look at me enough
    • Reference link two: Tencent Bugly dry goods share: WKWebView those pits
  • WebViewJavascriptBridge
    • Link 1: GitHub WebViewJavascriptBridge framework download link
    • Link 2: WebViewJavascriptBridge principle parsing
    • Link 3: Objective-C and JavaScript interaction stuff