热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

WKWebView的使用(iOS8.0及以上版本使用)替代UIWebView

Demo实例在iOS开发中,调用web页面时,最常用的就是UIWebView控件。但在使用过程中,也让大家觉得很不爽,就是内存爆增。自从iOS8.0以后有了WKWebView,这种情

Demo实例

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

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

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

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

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

 

WKWebView的特点:

1 拥有 60fps滚动刷新率

2 内置手势

3 高效的 app web信息交换通道

4 Safari相同的 Javascript引擎

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


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




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

1、导入头文件

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0
#import
#endif
2、添加协议及定义 WKWebView

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

@interface WKWebViewVC () 

@property (nonatomic, strong) WKWebView *webview;

@end
- (WKWebView *)webview{    if (_webview == nil)    {        _webview = [[WKWebView alloc] init];        _webview.frame = self.view.bounds;        _webview.backgroundColor = [UIColor clearColor];                _webview.UIDelegate = self;        _webview.navigatiOnDelegate= self;            }        return _webview;}
[self.view addSubview:self.webview];
3、实现代理方法

3-1、WKUIDelegate代理方法

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

/// 创建一个新的WebView
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
{
NSLog(@"加载:打开内部链接");

// 打开内部链接
return self.webview;

// 不打开
// return nil;
}
/// 输入框- (void)webView:(WKWebView *)webView runJavascriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler{    NSLog(@"加载:输入框提示");        completionHandler(@"Client Not handler");}
/// 确认框- (void)webView:(WKWebView *)webView runJavascriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler{    NSLog(@"加载:确认框提示");        //  js 里面的alert实现,如果不实现,网页的alert函数无效    UIAlertController *alertCOntroller= [UIAlertController alertControllerWithTitle:message                                                                             message:nil                                                                      preferredStyle:UIAlertControllerStyleAlert];    [alertController addAction:[UIAlertAction actionWithTitle:@"确定"                                                        style:UIAlertActionStyleDefault                                                      handler:^(UIAlertAction *action) {                                                          completionHandler(YES);                                                      }]];    [alertController addAction:[UIAlertAction actionWithTitle:@"取消"                                                        style:UIAlertActionStyleCancel                                                      handler:^(UIAlertAction *action){                                                          completionHandler(NO);                                                      }]];        [self presentViewController:alertController animated:YES completion:^{}];}
/// 警告框- (void)webView:(WKWebView *)webView runJavascriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{    NSLog(@"加载:警告框提示");        // js 里面的alert实现,如果不实现,网页的alert函数无效    UIAlertController *alertCOntroller= [UIAlertController alertControllerWithTitle:message                                                                             message:nil                                                                      preferredStyle:UIAlertControllerStyleAlert];    [alertController addAction:[UIAlertAction actionWithTitle:@"确定"                                                        style:UIAlertActionStyleCancel                                                      handler:^(UIAlertAction *action) {                                                          completionHandler();                                                      }]];        [self presentViewController:alertController animated:YES completion:^{}];}
3-2、WKNavigationDelegate

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

/// 接收到服务器跳转请求之后调用 (服务器端redirect),不一定调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO ;

NSLog(@"加载:服务器跳转");
}

/// 1 在发送请求之前,决定是否跳转(注:不加上decisionHandler回调会造成闪退)
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES ;

NSLog(@"加载:发送请求是否跳转");


WKNavigationActionPolicy actiOnPolicy= WKNavigationActionPolicyAllow;
// 这句是必须加上的,不然会异常
decisionHandler(actionPolicy);
}
 
 
/// 2 页面开始加载
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES ;

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

NSLog(@"加载:开始获取信息");
}
/// 5 页面加载完成之后调用- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO ;        NSLog(@"加载:完成");}
/// 页面加载失败时调用- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation{    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO ;        NSLog(@"加载:失败");}

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

- (void)startClick
{
if ([_webview isLoading])
{
return;
}

NSURL *url = [NSURL URLWithString:@"http://www.hao123.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[_webview loadRequest:request];

NSLog(@"加载:启动");
}
- (void)stopClick{    if ([_webview isLoading])    {        [_webview stopLoading];                [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;                NSLog(@"加载:停止");    }}

注意:

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

- (void)dealloc
{
_webview.UIDelegate = nil;
_webview.navigatiOnDelegate= nil;
[_webview loadHTMLString:@"" baseURL:nil];
[_webview stopLoading];
[_webview removeFromSuperview];
[[NSURLCache sharedURLCache] removeAllCachedResponses];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

_webview = nil;
}

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

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

#pragma mark - 通知方法

- (void)observeProgress
{
// 进度条监视
CGFloat progress = self.webview.estimatedProgress;
NSLog(@"加载进度:%.2f", progress);

[self.webview addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
// 进度条
if ([@"estimatedProgress" isEqualToString:keyPath])
{
CGFloat progress = self.webview.estimatedProgress;
NSLog(@"正在加载中,加载进度:%.2f", progress);

// 初始和终止状态
if (progress == 0.0)
{
NSLog(@"加载开始,进度条值:0.0");
}
else if (progress == 1.0)
{
NSLog(@"加载结束,进度条值:1.0");

// 1秒后隐藏
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 再次判断,防止正在加载时有其他操作
if (progress == 1.0)
{
NSLog(@"加载结束,进度条值:1.0(异步)");
}
});
}
}
}
2016-09-30 17:10:47.121 DemoWebViewOptimize[16698:308353] 加载进度:0.002016-09-30 17:10:48.148 DemoWebViewOptimize[16698:308353] 正在加载中,加载进度:0.102016-09-30 17:10:48.148 DemoWebViewOptimize[16698:308353] 加载:启动2016-09-30 17:10:48.160 DemoWebViewOptimize[16698:308353] 加载:发送请求是否跳转2016-09-30 17:10:48.170 DemoWebViewOptimize[16698:308353] 加载:开始2016-09-30 17:10:48.273 DemoWebViewOptimize[16698:308353] 加载:发送请求是否跳转2016-09-30 17:10:48.274 DemoWebViewOptimize[16698:308353] 加载:服务器跳转2016-09-30 17:10:48.326 DemoWebViewOptimize[16698:308353] 加载:发送请求是否跳转2016-09-30 17:10:48.327 DemoWebViewOptimize[16698:308353] 加载:服务器跳转2016-09-30 17:10:48.468 DemoWebViewOptimize[16698:308353] 加载:服务器响应头2016-09-30 17:10:48.469 DemoWebViewOptimize[16698:308353] 正在加载中,加载进度:0.302016-09-30 17:10:48.527 DemoWebViewOptimize[16698:308353] 加载:开始获取信息2016-09-30 17:10:48.635 DemoWebViewOptimize[16698:308353] 加载:发送请求是否跳转2016-09-30 17:10:48.692 DemoWebViewOptimize[16698:308353] 正在加载中,加载进度:0.852016-09-30 17:10:48.713 DemoWebViewOptimize[16698:308353] 加载:服务器响应头2016-09-30 17:10:48.923 DemoWebViewOptimize[16698:308353] 正在加载中,加载进度:0.902016-09-30 17:10:48.989 DemoWebViewOptimize[16698:308353] 加载:发送请求是否跳转2016-09-30 17:10:48.991 DemoWebViewOptimize[16698:308353] 加载:服务器响应头2016-09-30 17:10:49.008 DemoWebViewOptimize[16698:308353] 加载:发送请求是否跳转2016-09-30 17:10:49.188 DemoWebViewOptimize[16698:308353] 正在加载中,加载进度:0.902016-09-30 17:10:49.197 DemoWebViewOptimize[16698:308353] 加载:服务器响应头2016-09-30 17:10:49.198 DemoWebViewOptimize[16698:308353] 正在加载中,加载进度:1.002016-09-30 17:10:49.199 DemoWebViewOptimize[16698:308353] 加载结束,进度条值:1.02016-09-30 17:10:49.199 DemoWebViewOptimize[16698:308353] 加载:完成2016-09-30 17:10:49.328 DemoWebViewOptimize[16698:308353] 加载:发送请求是否跳转2016-09-30 17:10:49.384 DemoWebViewOptimize[16698:308353] 加载:服务器响应头2016-09-30 17:10:49.855 DemoWebViewOptimize[16698:308353] 加载:发送请求是否跳转2016-09-30 17:10:49.900 DemoWebViewOptimize[16698:308353] 加载:服务器响应头2016-09-30 17:10:50.293 DemoWebViewOptimize[16698:308353] 加载结束,进度条值:1.0(异步)


注意:

代理方法使用说明

// 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;

// 2 WKNavigtionDelegate来进行页面跳转
// 接收到服务器跳转请求之后再执行
- (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;

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





















推荐阅读
author-avatar
惰堂_301
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有