WKWebView新特性

在WWDC2014中,苹果推出了最新的iOS8系统,其中也伴随着很多控件的更新与升级。其中全新的WebKit库让人很是兴奋。本文也将讲解到WebKit中更新的WKWebView控件的新特性与使用方法,它很好的解决了UIWebView存在的内存、加载速度等诸多问题。

环境信息:

Mac OS X 10.10.1

Xcode 6.1.1

iOS 8.1

正文:

一、WKWebView新特性

  • 在性能、稳定性、功能方面有很大提升(最直观的体现就是加载网页是占用的内存,模拟器加载百度与开源中国网站时,WKWebView占用23M,而UIWebView占用85M);
  • 允许JavaScript的Nitro库加载并使用(UIWebView中限制);
  • 支持了更多的HTML5特性
  • 高达60fps的滚动刷新率以及内置手势
  • 将UIWebViewDelegate与UIWebView重构成了14类与3个协议(查看苹果官方文档);

二、初始化

1. 首先需要引入WebKit库

 #import <WebKit/WebKit.h> 

2. 初始化方法分为以下两种

 // 默认初始化 - (instancetype)initWithFrame:(CGRect)frame; // 根据对webview的相关配置,进行初始化 - (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER; 

3. 加载网页与HTML代码的方式与UIWebView相同,代码如下:

 WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds]; [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]]; [self.view addSubview:webView]; 

三、 WKWebView的代理方法

1. WKNavigationDelegate

该代理提供的方法,可以用来追踪加载过程(页面开始加载、加载完成、加载失败)、决定是否执行跳转。

 // 页面开始加载时调用 - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation; // 当内容开始返回时调用 - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation; // 页面加载完成之后调用 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation; // 页面加载失败时调用 - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation; 

页面跳转的代理方法有三种,分为(收到跳转与决定是否跳转两种)

 // 接收到服务器跳转请求之后调用 - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation; // 在收到响应后,决定是否跳转 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler; // 在发送请求之前,决定是否跳转 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler; 

2. WKUIDelegate

 // 创建一个新的WebView - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures; 

剩下三个代理方法全都是与界面弹出提示框相关的,针对于web界面的三种提示框(警告框、确认框、输入框)分别对应三种代理方法。下面只举了警告框的例子。

 /** * web界面中有弹出警告框时调用 * * @param webView 实现该代理的webview * @param message 警告框中的内容 * @param frame 主窗口 * @param completionHandler 警告框消失调用 */ - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(void (^)())completionHandler; 

3. WKScriptMessageHandler

这个协议中包含一个必须实现的方法,这个方法是提高App与web端交互的关键,它可以直接将接收到的JS脚本转为OC或Swift对象。(当然,在UIWebView也可以通过“曲线救国”的方式与web进行交互,著名的Cordova框架就是这种机制)

 // 从web界面中接收到一个脚本时调用 - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message; 

四、WKWebView加载JS

 // 图片缩放的js代码 NSString *js = @"var count = document.images.length;for (var i = 0; i < count; i++) {var image = document.images[i];image.style.width=320;};window.alert('找到' + count + '张图');"; // 根据JS字符串初始化WKUserScript对象 WKUserScript *script = [[WKUserScript alloc] initWithSource:js injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES]; // 根据生成的WKUserScript对象,初始化WKWebViewConfiguration WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; [config.userContentController addUserScript:script]; _webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config]; [_webView loadHTMLString:@"<head></head><img src='http://www.nsu.edu.cn/v/2014v3/img/background/3.jpg' />"baseURL:nil]; [self.view addSubview:_webView]; 

五、本文Demo下载

 https://github.com/saitjr/WKWebViewSimpleDemo.git

六、关于JS的加载或WebView的其他使用技巧,可查看一下文章:

使用Safari对WebView进行调试

WebView加载HTML图片大小自适应与文章自动换行

参考资料:

http://nshipster.cn/wkwebkit/

http://www.cocoachina.com/webapp/20141121/10277.html

http://blog.csdn.net/cyforce/article/details/37657009

下面讲一讲 WkWebView的一些使用方法
  1. - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation { // 类似UIWebView的 -webViewDidStartLoad:  
  2.     NSLog(@"didStartProvisionalNavigation");  
  3.     [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;  
  4. }  
  5.   
  6. - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {  
  7.     NSLog(@"didCommitNavigation");  
  8. }  
  9.   
  10. - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { // 类似 UIWebView 的 -webViewDidFinishLoad:  
  11.     NSLog(@"didFinishNavigation");  
  12.     [self resetControl];  
  13.     if (webView.title.length > 0) {  
  14.         self.title = webView.title;  
  15.     }  
  16.   
  17. }  
  18. - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {  
  19.     // 类似 UIWebView 的- webView:didFailLoadWithError:  
  20.   
  21.     NSLog(@"didFailProvisionalNavigation");  
  22.       
  23. }  
  24. - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {  
  25.       
  26.     decisionHandler(WKNavigationResponsePolicyAllow);  
  27. }  
  28.   
  29.   
  30. - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {  
  31.     // 类似 UIWebView 的 -webView: shouldStartLoadWithRequest: navigationType:  
  32.   
  33.     NSLog(@"4.%@",navigationAction.request);  
  34.   
  35.       
  36.     NSString *url = [navigationAction.request.URL.absoluteString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];  
  37.   
  38.       
  39.       
  40.     decisionHandler(WKNavigationActionPolicyAllow);  
  41.   
  42. }  
  43. - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler {  
  44.       
  45. }  

2 UIDelegate

  1. - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {  
  2.     // 接口的作用是打开新窗口委托  
  3.     [self createNewWebViewWithURL:webView.URL.absoluteString config:configuration];  
  4.       
  5.     return currentSubView.webView;  
  6. }  
  7.   
  8. - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)())completionHandler  
  9. {    // js 里面的alert实现,如果不实现,网页的alert函数无效  
  10.     UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message  
  11.                                                                              message:nil  
  12.                                                                       preferredStyle:UIAlertControllerStyleAlert];  
  13.     [alertController addAction:[UIAlertAction actionWithTitle:@"确定"  
  14.                                                         style:UIAlertActionStyleCancel  
  15.                                                       handler:^(UIAlertAction *action) {  
  16.                                                           completionHandler();  
  17.                                                       }]];  
  18.       
  19.     [self presentViewController:alertController animated:YES completion:^{}];  
  20.       
  21. }  
  22.   
  23.   
  24. - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {  
  25.     //  js 里面的alert实现,如果不实现,网页的alert函数无效  ,   
  26.   
  27.     UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message  
  28.                                                                              message:nil  
  29.                                                                       preferredStyle:UIAlertControllerStyleAlert];  
  30.     [alertController addAction:[UIAlertAction actionWithTitle:@"确定"  
  31.                                                         style:UIAlertActionStyleDefault  
  32.                                                       handler:^(UIAlertAction *action) {  
  33.                                                           completionHandler(YES);  
  34.                                                       }]];  
  35.     [alertController addAction:[UIAlertAction actionWithTitle:@"取消"  
  36.                                                         style:UIAlertActionStyleCancel  
  37.                                                       handler:^(UIAlertAction *action){  
  38.                                                           completionHandler(NO);  
  39.                                                       }]];  
  40.       
  41.     [self presentViewController:alertController animated:YES completion:^{}];  
  42.       
  43. }  
  44.   
  45. - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *))completionHandler {  
  46.       
  47.     completionHandler(@"Client Not handler");  
  48.       
  49. }  


3. WKWebView 执行脚本方法


  1. - (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^)(idNSError *))completionHandler;  

  1. completionHandler 拥有两个参数,一个是返回错误,一个可以返回执行脚本后的返回值  

4. WKWebView 的Cookie问题

UIWebView 中会自动保存Cookie,如果登录了一次,下次再次进入的时候,会记住登录状态

而在WKWebView中,并不会这样,WKWebView在初始化的时候有一个方法

  1. - (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration  

通过这个方法,设置 configuration 让WKWebView知道登录状态,configuration 可以通过已有的Cookie进行设置,也可以通过保存上一次的configuration进行设置

参考 stackoverflow上回答:http://stackoverflow.com/questions/26573137/can-i-set-the-cookies-to-be-used-by-a-wkwebview/26577303#26577303
  1. WKWebView * webView = /*set up your webView*/  
  2. NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://example.com/index.html"]];  
  3. [request addValue:@"TeskCookieKey1=TeskCookieValue1;TeskCookieKey2=TeskCookieValue2;" forHTTPHeaderField:@"Cookie"];  
  4. // use stringWithFormat: in the above line to inject your values programmatically  
  5. [webView loadRequest:request];  

  1. WKUserContentController* userContentController = WKUserContentController.new;  
  2. WKUserScript * cookieScript = [[WKUserScript alloc]   
  3.     initWithSource@"document.cookie = 'TeskCookieKey1=TeskCookieValue1';document.cookie = 'TeskCookieKey2=TeskCookieValue2';"  
  4.     injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];  
  5. // again, use stringWithFormat: in the above line to inject your values programmatically  
  6. [userContentController addUserScript:cookieScript];  
  7. WKWebViewConfiguration* webViewConfig = WKWebViewConfiguration.new;  
  8. webViewConfig.userContentController = userContentController;  
  9. WKWebView * webView = [[WKWebView alloc] initWithFrame:CGRectMake(/*set your values*/) configuration:webViewConfig];  

你可能感兴趣的:(WKWebView,UIWeView,UIWebView优化)