信息内容
您现在的位置:首页-信息内容
WKWebView的使用(iOS8.0及以上版本使用)替代UIWebView 发布日期:2018-6-10 来源:csdn 【关闭】

在iOS开发中,调用web页面时,最常用的就是

UIWebView控件。但在使用过程中,也让大家觉得很不爽,就是内存爆增。

自从iOS8.0以后有了WKWebView,这种情况就好转了。因为在使用WKWebView的过程中基本上内存保持不变。

WKWebView 是现代 WebKit API iOS 8 OS X Yosemite应用中的核心部分。

WKWebView 代替了 UIKit中的 UIWebView AppKit中的 WebView,提供了统一的跨双平台 API

 

WKWebView的特点:

拥有 60fps滚动刷新率

内置手势

高效的 app web信息交换通道

 Safari相同的 JavaScript引擎

性能高,稳定性好,占用的内存比较小


下面两图分别是使用WKWebView、UIWebView时的内存情况


WKWebView怎么使用呢?话不多说,直接上码。

1、导入头文件

[objc] view plain copy
  1. #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0  
  2. #import <WebKit/WebKit.h>  
  3. #endif  
2、添加协议及定义WKWebView

在这里我定义成属性使用,同时使用getter方法进行实例化,实例化后记得要添加到父视图。

[objc] view plain copy
  1. @interface WKWebViewVC () <WKUIDelegate, WKNavigationDelegate>  
  2.   
  3. @property (nonatomicstrongWKWebView *webview;  
  4.   
  5. @end  
[objc] view plain copy
  1. - (WKWebView *)webview  
  2. {  
  3.     if (_webview == nil)  
  4.     {  
  5.         _webview = [[WKWebView alloc] init];  
  6.         _webview.frame = self.view.bounds;  
  7.         _webview.backgroundColor = [UIColor clearColor];  
  8.           
  9.         _webview.UIDelegate = self;  
  10.         _webview.navigationDelegate = self;  
  11.           
  12.     }  
  13.       
  14.     return _webview;  
  15. }  
[objc] view plain copy
  1. [self.view addSubview:self.webview];  
3、实现代理方法

3-1、WKUIDelegate代理方法

UI界面相关,原生控件支持,三种提示框:输入、确认、警告。首先将web提示框拦截然后再做处理

[objc] view plain copy
  1. /// 创建一个新的WebView  
  2. - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures  
  3. {  
  4.     NSLog(@"加载:打开内部链接");  
  5.       
  6.     // 打开内部链接  
  7.     return self.webview;  
  8.       
  9.     // 不打开  
  10. //    return nil;  
  11. }  
[objc] view plain copy
  1. /// 输入框  
  2. - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler  
  3. {  
  4.     NSLog(@"加载:输入框提示");  
  5.       
  6.     completionHandler(@"Client Not handler");  
  7. }  
[objc] view plain copy
  1. /// 确认框  
  2. - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler  
  3. {  
  4.     NSLog(@"加载:确认框提示");  
  5.       
  6.     //  js 里面的alert实现,如果不实现,网页的alert函数无效  
  7.     UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message  
  8.                                                                              message:nil  
  9.                                                                       preferredStyle:UIAlertControllerStyleAlert];  
  10.     [alertController addAction:[UIAlertAction actionWithTitle:@"确定"  
  11.                                                         style:UIAlertActionStyleDefault  
  12.                                                       handler:^(UIAlertAction *action) {  
  13.                                                           completionHandler(YES);  
  14.                                                       }]];  
  15.     [alertController addAction:[UIAlertAction actionWithTitle:@"取消"  
  16.                                                         style:UIAlertActionStyleCancel  
  17.                                                       handler:^(UIAlertAction *action){  
  18.                                                           completionHandler(NO);  
  19.                                                       }]];  
  20.       
  21.     [self presentViewController:alertController animated:YES completion:^{}];  
  22. }  
[objc] view plain copy
  1. /// 警告框  
  2. - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler  
  3. {  
  4.     NSLog(@"加载:警告框提示");  
  5.       
  6.     // js 里面的alert实现,如果不实现,网页的alert函数无效  
  7.     UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message  
  8.                                                                              message:nil  
  9.                                                                       preferredStyle:UIAlertControllerStyleAlert];  
  10.     [alertController addAction:[UIAlertAction actionWithTitle:@"确定"  
  11.                                                         style:UIAlertActionStyleCancel  
  12.                                                       handler:^(UIAlertAction *action) {  
  13.                                                           completionHandler();  
  14.                                                       }]];  
  15.       
  16.     [self presentViewController:alertController animated:YES completion:^{}];  
  17. }  
3-2、WKNavigationDelegate

追踪加载过程,有是否允许加载、开始加载、加载完成、加载失败

[objc] view plain copy
  1. /// 接收到服务器跳转请求之后调用 (服务器端redirect),不一定调用  
  2. - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation  
  3. {  
  4.     [UIApplication sharedApplication].networkActivityIndicatorVisible = NO ;  
  5.       
  6.     NSLog(@"加载:服务器跳转");  
  7. }  
[objc] view plain copy
  1. /// 1 在发送请求之前,决定是否跳转(注:不加上decisionHandler回调会造成闪退)  
  2. - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler  
  3. {  
  4.     [UIApplication sharedApplication].networkActivityIndicatorVisible = YES ;  
  5.       
  6.     NSLog(@"加载:发送请求是否跳转");  
  7.   
  8.       
  9.     WKNavigationActionPolicy actionPolicy = WKNavigationActionPolicyAllow;  
  10.     // 这句是必须加上的,不然会异常  
  11.     decisionHandler(actionPolicy);  
  12. }  

[objc] view plain copy
  1. /// 2 页面开始加载  
  2. - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation  
  3. {  
  4.     [UIApplication sharedApplication].networkActivityIndicatorVisible = YES ;  
  5.       
  6.     NSLog(@"加载:开始");  
  7. }  
[objc] view plain copy
  1. /// 3 在收到服务器的响应头,根据response相关信息,决定是否跳转。decisionHandler必须调用,来决定是否跳转,参数WKNavigationActionPolicyCancel取消跳转,WKNavigationActionPolicyAllow允许跳转(注:不加上decisionHandler回调会造成闪退)  
  2. - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler  
  3. {  
  4.     NSLog(@"加载:服务器响应头");  
  5.       
  6.     WKNavigationResponsePolicy responsePolicy = WKNavigationResponsePolicyAllow;  
  7.     // 这句是必须加上的,不然会异常  
  8.     decisionHandler(responsePolicy);  
  9. }  

[objc] view plain copy
  1. /// 4 开始获取到网页内容时返回  
  2. - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation  
  3. {  
  4.     [UIApplication sharedApplication].networkActivityIndicatorVisible = YES ;  
  5.       
  6.     NSLog(@"加载:开始获取信息");  
  7. }  
[objc] view plain copy
  1. /// 5 页面加载完成之后调用  
  2. - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation  
  3. {  
  4.     [UIApplication sharedApplication].networkActivityIndicatorVisible = NO ;  
  5.       
  6.     NSLog(@"加载:完成");  
  7. }  
[objc] view plain copy
  1. /// 页面加载失败时调用  
  2. - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation  
  3. {  
  4.     [UIApplication sharedApplication].networkActivityIndicatorVisible = NO ;  
  5.       
  6.     NSLog(@"加载:失败");  
  7. }  

4、打开web页面,或停止加载web页面

[objc] view plain copy
  1. - (void)startClick  
  2. {  
  3.     if ([_webview isLoading])  
  4.     {  
  5.         return;  
  6.     }  
  7.       
  8.     NSURL *url = [NSURL URLWithString:@"http://www.hao123.com"];  
  9.     NSURLRequest *request = [NSURLRequest requestWithURL:url];  
  10.     [_webview loadRequest:request];  
  11.       
  12.     NSLog(@"加载:启动");  
  13. }  
[objc] view plain copy
  1. - (void)stopClick  
  2. {  
  3.     if ([_webview isLoading])  
  4.     {  
  5.         [_webview stopLoading];  
  6.           
  7.         [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;  
  8.           
  9.         NSLog(@"加载:停止");  
  10.     }  
  11. }  

注意:

1、视图控制器释放时,注意内存管理。

[html] view plain copy
  1. - (void)dealloc  
  2. {  
  3.     _webview.UIDelegate = nil;  
  4.     _webview.navigationDelegate = nil;  
  5.     [_webview loadHTMLString:@"" baseURL:nil];  
  6.     [_webview stopLoading];  
  7.     [_webview removeFromSuperview];  
  8.     [[NSURLCache sharedURLCache] removeAllCachedResponses];  
  9.     [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;  
  10.       
  11.     _webview = nil;  
  12. }  

2、WKWebView有个监视加载进度的属性"estimatedProgress"

注意:kvo使用时path名称必须是"estimatedProgress",或者"NSStringFromSelector(@selector(estimatedProgress))
",否则会造成异常闪退。

[html] view plain copy
  1. #pragma mark - 通知方法  
  2.   
  3. - (void)observeProgress  
  4. {  
  5.     // 进度条监视  
  6.     CGFloat progress = self.webview.estimatedProgress;  
  7.     NSLog(@"加载进度:%.2f", progress);  
  8.       
  9.     [self.webview addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];  
  10. }  
  11.   
  12. - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context  
  13. {  
  14.     // 进度条  
  15.     if ([@"estimatedProgress" isEqualToString:keyPath])  
  16.     {  
  17.         CGFloat progress = self.webview.estimatedProgress;  
  18.         NSLog(@"正在加载中,加载进度:%.2f", progress);  
  19.        
  20.         // 初始和终止状态  
  21.         if (progress == 0.0)  
  22.         {  
  23.             NSLog(@"加载开始,进度条值:0.0");  
  24.         }  
  25.         else if (progress == 1.0)  
  26.         {  
  27.             NSLog(@"加载结束,进度条值:1.0");  
  28.               
  29.             // 1秒后隐藏  
  30.             dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{  
  31.                 // 再次判断,防止正在加载时有其他操作  
  32.                 if (progress == 1.0)  
  33.                 {  
  34.                     NSLog(@"加载结束,进度条值:1.0(异步)");  
  35.                 }  
  36.             });  
  37.         }  
  38.     }  
  39. }  
[html] view plain copy
  1. 2016-09-30 17:10:47.121 DemoWebViewOptimize[16698:308353] 加载进度:0.00  
  2. 2016-09-30 17:10:48.148 DemoWebViewOptimize[16698:308353] 正在加载中,加载进度:0.10  
  3. 2016-09-30 17:10:48.148 DemoWebViewOptimize[16698:308353] 加载:启动  
  4. 2016-09-30 17:10:48.160 DemoWebViewOptimize[16698:308353] 加载:发送请求是否跳转  
  5. 2016-09-30 17:10:48.170 DemoWebViewOptimize[16698:308353] 加载:开始  
  6. 2016-09-30 17:10:48.273 DemoWebViewOptimize[16698:308353] 加载:发送请求是否跳转  
  7. 2016-09-30 17:10:48.274 DemoWebViewOptimize[16698:308353] 加载:服务器跳转  
  8. 2016-09-30 17:10:48.326 DemoWebViewOptimize[16698:308353] 加载:发送请求是否跳转  
  9. 2016-09-30 17:10:48.327 DemoWebViewOptimize[16698:308353] 加载:服务器跳转  
  10. 2016-09-30 17:10:48.468 DemoWebViewOptimize[16698:308353] 加载:服务器响应头  
  11. 2016-09-30 17:10:48.469 DemoWebViewOptimize[16698:308353] 正在加载中,加载进度:0.30  
  12. 2016-09-30 17:10:48.527 DemoWebViewOptimize[16698:308353] 加载:开始获取信息  
  13. 2016-09-30 17:10:48.635 DemoWebViewOptimize[16698:308353] 加载:发送请求是否跳转  
  14. 2016-09-30 17:10:48.692 DemoWebViewOptimize[16698:308353] 正在加载中,加载进度:0.85  
  15. 2016-09-30 17:10:48.713 DemoWebViewOptimize[16698:308353] 加载:服务器响应头  
  16. 2016-09-30 17:10:48.923 DemoWebViewOptimize[16698:308353] 正在加载中,加载进度:0.90  
  17. 2016-09-30 17:10:48.989 DemoWebViewOptimize[16698:308353] 加载:发送请求是否跳转  
  18. 2016-09-30 17:10:48.991 DemoWebViewOptimize[16698:308353] 加载:服务器响应头  
  19. 2016-09-30 17:10:49.008 DemoWebViewOptimize[16698:308353] 加载:发送请求是否跳转  
  20. 2016-09-30 17:10:49.188 DemoWebViewOptimize[16698:308353] 正在加载中,加载进度:0.90  
  21. 2016-09-30 17:10:49.197 DemoWebViewOptimize[16698:308353] 加载:服务器响应头  
  22. 2016-09-30 17:10:49.198 DemoWebViewOptimize[16698:308353] 正在加载中,加载进度:1.00  
  23. 2016-09-30 17:10:49.199 DemoWebViewOptimize[16698:308353] 加载结束,进度条值:1.0  
  24. 2016-09-30 17:10:49.199 DemoWebViewOptimize[16698:308353] 加载:完成  
  25. 2016-09-30 17:10:49.328 DemoWebViewOptimize[16698:308353] 加载:发送请求是否跳转  
  26. 2016-09-30 17:10:49.384 DemoWebViewOptimize[16698:308353] 加载:服务器响应头  
  27. 2016-09-30 17:10:49.855 DemoWebViewOptimize[16698:308353] 加载:发送请求是否跳转  
  28. 2016-09-30 17:10:49.900 DemoWebViewOptimize[16698:308353] 加载:服务器响应头  
  29. 2016-09-30 17:10:50.293 DemoWebViewOptimize[16698:308353] 加载结束,进度条值:1.0(异步)  


注意:

代理方法使用说明

[html] view plain copy
  1. // 1 WKNavigationDelegate来追踪加载过程  
  2. // 页面开始加载时调用  
  3. - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation;  
  4. // 当内容开始返回时调用  
  5. - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation;  
  6. // 页面加载完成之后调用  
  7. - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation;  
  8. // 页面加载失败时调用  
  9. - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation;  

[html] view plain copy
  1. // 2 WKNavigtionDelegate来进行页面跳转  
  2. // 接收到服务器跳转请求之后再执行  
  3. - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation;  
  4. // 在收到响应后,决定是否跳转  
  5. - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;  
  6. // 在发送请求之前,决定是否跳转  
  7. - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;  

[html] view plain copy
  1. // 3  WKUIDelegate(PS:WKUIDelegate主要是做跟网页交互的,可以显示javascript的一些alert或者Action,看起来跟自己做的一样的.)  
  2. // 创建一个新的WebVeiw  
  3. - (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;  
  4. // WebVeiw关闭(9.0中的新方法)  
  5. - (void)webViewDidClose:(WKWebView *)webView NS_AVAILABLE(10_11, 9_0);  
  6. // 显示一个JS的Alert(与JS交互)  
  7. - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;  
  8. // 弹出一个输入框(与JS交互的)  
  9. - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler;  
  10. // 显示一个确认框(JS的)  
  11. - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler;  


成都世帆软件    交通运输综合执法系统软件、公路路政执法系统软件、道路运政执法系统软件、海事行政、水路运政、航道行政、港口行政执法 管理系统软件定制开发

交通综合执法系统、公路路政执法管理系统、超限运输管理系统、道路运政执法管理系统、运管执法管理系统、公路养护管理系统、公路运行监测系统
市场监管执法软件、工商行政执法软件、环境监察执法软件、城市管理执法软件、食品卫生执法软件

备案号:蜀ICP备12010221号-20    电-话:028-8768 9944