A. WKWebView Framework

WKWebView has 14 classes and 3 protocols

==WKBackForwardList==: A list of previously visited Web pages, which can be queried by the back and forward action visits.

==WKBackForwardListItem==: a web page in the back list of the WebView.

==WKFrameInfo==: Contains the layout information of a web page.

==WKNavigation==: contains information about the loading progress of a page.

==WKNavigationAction==: Contains information that may cause navigation changes to the page, used to determine whether to make navigation changes.

==WKNavigationResponse==: Contains information about the returned content that may change the navigation of the page, used to determine whether to make navigation changes.

==WKPreferences==: Generalize a WebView’s preferences.

==WKProcessPool==: Indicates a Web content loading pool.

==WKUserContentController==: provides methods to use JavaScript to post messages and inject scripts.

==WKScriptMessage==: Contains the message sent by the web page.

==WKUserScript==: Indicates the user script that can be accepted by the web page.

==WKWebViewConfiguration==: Initializes webView Settings.

==WKWindowFeatures==: Specifies window properties when loading a new web page.

==WKWebsiteDataStore==: Contains web page data storage and lookup.

==WKNavigationDelegate==: provides a method to track the main window page loading process and determine whether the main window and child window page loading new page.

==WKUIDelegate==: Provides method callbacks to display web pages with native controls.

==WKScriptMessageHandler==: Provides a callback method to receive messages from the web page.

Three agents in WKWebView

  1. WKNavigationDelegate The agent provides methods that can be used to track the loading process (the page starts loading, the page finishes loading, the page fails loading) and determine whether to perform a jump.
/ / start page load when the - (void) webView: (WKWebView *) webView didStartProvisionalNavigation (WKNavigation *) navigation; // call - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation; // Call - (void)webView (WKWebView *)webView didFinishNavigation (WKNavigation *)navigation; / / page load when the - (void) failure webView: (WKWebView *) webView didFailProvisionalNavigation (WKNavigation *) navigation;Copy the code

There are three proxy methods of page jump, divided into (receive jump and decide whether to jump two)

/ / receive the server after the jump request call - (void) webView: (WKWebView *) webView didReceiveServerRedirectForProvisionalNavigation: (WKNavigation *)navigation; // After receiving the response, Deciding whether to jump - (void) webView: (WKWebView *) webView decidePolicyForNavigationResponse: (navigationResponse WKNavigationResponse *)  decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler; // Before sending the request, Deciding whether to jump - (void) webView: (WKWebView *) webView decidePolicyForNavigationAction: (navigationAction WKNavigationAction *) decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;Copy the code
  1. WKUIDelegate
/ / create a new WebView - (WKWebView *) WebView: (WKWebView *) WebView createWebViewWithConfiguration: (WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;Copy the code

The remaining three proxy methods are all related to pop-up prompt boxes. The three prompt boxes (warning, confirmation, and input) on the Web interface correspond to three proxy methods respectively.

/ / interface pop-up warning box - (void) webView: (WKWebView *) webView runJavaScriptAlertPanelWithMessage message: (nsstrings *) initiatedByFrame:(void (^)())completionHandler; / / interface pop-up confirmation box - (void) webView: (WKWebView *) webView runJavaScriptConfirmPanelWithMessage message: (nsstrings *) initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler; / / interface pop-up box - (void) webView: (WKWebView *) webView runJavaScriptTextInputPanelWithPrompt prompt: (nsstrings *) defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler;Copy the code
  1. WKScriptMessageHandle

This protocol contains a method that must be implemented. This method is the key for native to interact with the Web side. It can directly convert the RECEIVED JS scripts into OC or Swift objects.

- (void)userContentController:(WKUserContentController *)userContentController is called when a script is received from the web interface didReceiveScriptMessage:(WKScriptMessage *)message;Copy the code

Three, using WKWebView rewrite

Here we have made a little change with the previous interface. Before, OC called JS for popbox processing. Here I was very frustrated when I was writing, the method could be called, but only the JS alert method had no effect. WKWebView does not support NIB files, so you need to initialize and load the WebView using code

WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.preferences.minimumFontSize = 18;
 
self.wkWebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height/2) configuration:config];
[self.view addSubview:self.wkWebView];
 
 
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSURL *baseURL = [[NSBundle mainBundle] bundleURL];
[self.wkWebView loadHTMLString:[NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil] baseURL:baseURL];
Copy the code

OC side:

/ / 1. Add processing script JS calls OC [userCC addScriptMessageHandler: self name: @ "showMobile"]. [userCC addScriptMessageHandler:self name:@"showName"]; [userCC addScriptMessageHandler:self name:@"showSendMsg"]; // handle the corresponding event in the proxy method - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { NSLog(@"%@",NSStringFromSelector(_cmd)); NSLog(@"%@",message.body); If ([message.name isEqualToString:@"showMobile"]) {[self showMsg:@" showMobile"]; } if ([message.name isEqualToString:@"showName"]) {NSString *info = [NSString stringWithFormat:@" Hello %@, Nice to meet you ",message.body]; [self showMsg:info]; } if ([message.name isEqualToString:@"showSendMsg"]) { NSArray *array = message.body; Nsstrings * info = [nsstrings stringWithFormat: @ "this is my mobile number: % @, % @!!", array. FirstObject, array. LastObject]; [self showMsg:info]; }} // 2. Native call js - (IBAction)btnClick:(UIButton *)sender {if (! self.wkWebView.loading) { if (sender.tag == 123) { [self.wkWebView evaluateJavaScript:@"alertMobile()" completionHandler:^(id _Nullable response, NSError * _Nullable error) { //TODO NSLog(@"%@ %@",response,error); }]; } if (sender.tag == 234) {self.wkWebView evaluateJavaScript:@"alertName(' red ')" completionHandler:nil]; Self. wkWebView evaluateJavaScript: @alertsendmsg ('18870707070',' What a nice thing to do at the weekend ') completionHandler:nil]; } } else { NSLog(@"the view is currently loading content"); }}Copy the code

JS end:

function clear() { document.getElementById('mobile').innerHTML = '' document.getElementById('name').innerHTML = '' Document.getelementbyid (' MSG ').innerhtml = "} function alert () {alert () //alert(' I am the top yellow phone number :13300001111') document.getelementById ('mobile').innerhtml = 'I am the top yellow phone number :13300001111'} function //alert(' hello '+ MSG + ') document.getelementById ('name').innerhtml =' hello '+ MSG + ', } function alertSendMsg(num, MSG) {//window.alert(' + num + ',' + MSG + '!! ') document.getelementById (' MSG ').innerhtml = 'this is my phone number :' + num + ',' + MSG + '!! '} / JS/response method list function btnClick1 () {window. Its. MessageHandlers. ShowMobile. PostMessage (null)} function btnClick2 () {window. Its. MessageHandlers. ShowName. PostMessage (' xiao huang ')} function btnClick3 () { window.webkit.messageHandlers.showSendMsg.postMessage(['13300001111', 'Go Climbing This Weekend !!!']) }Copy the code

Specific implementation process in rainbow project

WKWebView and JS interaction

  • Agent < WKUIDelegate WKNavigationDelegate, WKScriptMessageHandler >
  • @property(nonatomic,strong)WKWebView *webView;

Create a WebView

- (WKWebView *)webView {if (! _webView) { WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; Config. preferences = [[WKPreferences alloc]init]; The config / / default to 0. Preferences. MinimumFontSize = 0; / / the default value is YES config. Preferences. JavaScriptEnabled = YES; / / iOS default to NO, said can't automatically through the window to open the config. Preferences. JavaScriptCanOpenWindowsAutomatically = YES; WKUserContentController *userContent = [[WKUserContentController] alloc] init]; / / add message processing [userContent addScriptMessageHandler: self name: @ "longTapToSaveImage"]. / / will UserContentController config Settings to the configuration file. The UserContentController = userContent; _webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config]; _webView.allowsBackForwardNavigationGestures = NO; _webview. UIDelegate = self; _webView.navigationDelegate = self; // _webView.configuration.processPool; } return _webView; }Copy the code
#pragma mark - WKNavigationDelegate #pragma mark - WKNavigationDelegate Before sending the request, Deciding whether to jump - (void) webView: (WKWebView *) webView decidePolicyForNavigationAction: (navigationAction WKNavigationAction *) decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{ // CCLOG(@"goto:%@",webView.URL); decisionHandler(WKNavigationActionPolicyAllow); } - (void) webView: (WKWebView *) webView didStartProvisionalNavigation navigation: (WKNavigation *) {/ / tip can do here is loading animation Then remove the animation [self.view showMaskProgressHUD] in the loading completion agent method; } // called when the content starts to return -(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {} // called after the page is loaded -(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { // WKCookieSyncManager *cookiesManager = [WKCookieSyncManager sharedWKCookieSyncManager]; // [cookiesManager setCookie]; [self.view hiddenMaskProgressHUD] ; // NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; // self.cookies = [NSArray arrayWithArray:cookieStorage.cookies]; // // NSHTTPCookie *lostCookie = [cookieStorage.cookies lastObject]; // self.lostCookie = lostCookie; // // for (NSHTTPCookie *cookie in cookieStorage.cookies) { // NSLog(@"name = %@ value = %@",cookie.name,cookie.value); //} // //js function // NSString *JSFuncString = // @"function setCookie(name,value, Expires)\ // {\ // var oDate=new Date(); \ // oDate.setDate(oDate.getDate()+expires); \ // document.cookie=name+'='+value+'; expires='+oDate; \ // }\ // function getCookie(name)\ // {\ // var arr = document.cookie.match(new RegExp('(^| )'+name+'=([^;] (*). | $) ')); \ // if(arr ! = null) return unescape(arr[2]); return null; \ // }\ // function delCookie(name)\ // {\ // var exp = new Date(); \ // exp.setTime(exp.getTime() - 1); \ // var cval=getCookie(name); \ // if(cval! =null) document.cookie= name + '='+cval+'; expires='+exp.toGMTString(); / / /} "; // // // cobbler js string // NSMutableString *JSCookieString = jsFuncString. mutableCopy; // for (NSHTTPCookie *cookie in cookieStorage.cookies) { // NSString *excuteJSString = [NSString stringWithFormat:@"setCookie('%@', '%@', 1);", cookie.name, cookie.value]; // [JSCookieString appendString:excuteJSString]; // } // self.JSCookieString = JSCookieString; } / / page load when the - (void) failure webView: (WKWebView *) webView didFailProvisionalNavigation navigation: (WKNavigation *) withError:(nonnull NSError *)error { [self.view hiddenMaskProgressHUD] ; if ([error.description containsString:@"https://back/"]) { [self.navigationController popViewControllerAnimated:YES]; }else{ [CC_NoticeView showError:error.description]; }} / / HTTPS certificate through the - (void) webView: (WKWebView *) webView didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler { // if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { NSURLCredential *cred = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential, cred); //}} // we can handle it according to name and body. - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{ NSLog(@"%@",NSStringFromSelector(_cmd)); NSLog(@"%@",message); NSLog(@"%@",message.name); // method name NSLog(@"%@",message.body); NSString *messageName = message.name; if ([@"longTapToSaveImage" isEqualToString:messageName]) { id messageBody = message.body; NSLog(@"%@",messageBody); // write here the method to execute in OC [self saveImageUrl:(NSString *)messageBody]; }} / / remove the response - (void) dealloc {[self. WebView. Configuration. UserContentController removeScriptMessageHandlerForName:@"longTapToSaveImage"]; } - (void)saveImageUrl:(NSString *)imageUrlStr{ UIAlertController *alertController = [UIAlertController AlertControllerWithTitle: nil message: @ "whether to save the picture" preferredStyle: UIAlertControllerStyleAlert]; UIAlertAction * cancelAction = [UIAlertAction actionWithTitle: @ "cancel" style: UIAlertActionStyleCancel Handler :^(UIAlertAction * _Nonnull Action) {NSLog(@" Cancel button clicked ");}]; [alertController addAction:cancelAction]; UIAlertAction * defaultAction = [UIAlertAction actionWithTitle: @ "sure" style: UIAlertActionStyleDefault Handler :^(UIAlertAction * _Nonnull Action) {NSLog(@" make sure the button is clicked "); // Start an HTTPS request for the image // NSURL * URL = [NSURL URLWithString:imageUrlStr]; // [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:url] delegate:self]; // [self requestImageData:imageUrlStr]; NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrlStr]];  UIImage *image = [UIImage imageWithData:data]; if (image != nil) { [self imageSavedToPhotosAlbum:image]; } }]; [alertController addAction:defaultAction]; [self presentViewController:alertController animated:YES completion:nil]; } - (void)imageSavedToPhotosAlbum:(UIImage *)image{ [[RBCustomPhotoAlbum shareInstance]saveImageIntoAlbum:image withNeedReminder:YES]; }Copy the code

Related extensions of cookies