前言 由于之前一直在用UIWebView
,所以对于WKWebView
只是停留在知道,了解的状态,并未深入的去研究。前天一个项目要求支持iOS8以上,要加入一个web界面。在习惯性使用UIWebView
写到一半的时候,突然想使用WKWebView
去实现,所以专门花费了些时间去研究了一下WKWebView
,很是喜欢。
正文 接下来纪录一下使用WKWebView
的过程细节。但关于WKWebView
与js
互交的部分保留意见,因为并没有深入去研究这一点。
1、引入WebKit库 Apple方面为使用WKWebView
专门添加了WebKit
库,在使用WKWebView
时候必须引入WebKit
库才可以。
1 #import <WebKit/WebKit.h>
2、初始化WKWebView 在文档中可以看出,WKWebView
的初始化方法有两种:
1 2 - (instancetype)initWithFrame:(CGRect)frame; - (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER
我们大多使用第一种方式,这也是文档中默认的一种方式。这里不再多说。
关于第二种方式,其实就是在初始化WKWebView
时,给webView
做一个配置,我这里给出一段简单的配置代码:
1 2 3 4 5 6 7 8 WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc]init]; config.preferences = [WKPreferences new]; config.preferences.minimumFontSize = 20.f; config.preferences.javaScriptEnabled = YES; //The default value is YES config.preferences.javaScriptCanOpenWindowsAutomatically = NO;//The default value is NO in iOS and YES in OS X. //config.preferences.javaEnabled = NO ; //The default value is NO .不在iphone中使用的方法 config.userContentController = [WKUserContentController new]; self.webView = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:config];
注: 其实第一种方式,虽然我们并没有指定初始化的配置,但Apple也为我们指定了一个默认的配置。
3、加载网页 方法有几种,我们常用的是
1 2 NSURLRequest *request = [[NSURLRequest alloc]initWithURL:[NSURL URLWithString:@"https://www.baidu.com"]]; [self.webView loadRequest:request];
剩下的几种为:
1 2 3 4 5 [self.webView loadHTMLString:(nonnull NSString *) baseURL:(nullable NSURL *)]; [self.webView loadFileURL:(nonnull NSURL *) allowingReadAccessToURL:(nonnull NSURL *)]; [self.webView loadData:(nonnull NSData *) MIMEType:(nonnull NSString *) characterEncodingName:(nonnull NSString *) baseURL:(nonnull NSURL *)];
4、加载js代码 1 2 3 4 5 6 7 8 9 10 // 图片缩放的js代码 NSString *js = @"var count = document.images.length;for (var i = 0; i < count; i++) {var image = document.images[i];image.style.width=500;image.style.height=600;};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://og3hqoz3g.bkt.clouddn.com/%E5%B9%B8%E7%A6%8F%E9%82%AE%E5%B1%80.jpg' />"baseURL:nil]; [self.view addSubview:_webView];
5、代理 WKWebView
的代理有两个:WKNavigationDelegate
和 WKUIDelegate
5.1、 WKNavigationDelegate(加载界面时调用的协议方法)
过程:
在请求发送之前,决定是否跳转
页面开始加载时调用
在收到响应后,决定是否跳转
内容开始加载时调用
接收到服务器跳转请求之后调用(不一定调用该方法)
页面加载完成时调用
请求失败时调用
协议方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 //页面开始加载时调用 - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation { NSLog(@"页面开始加载时调用。 2"); } //内容返回时调用,得到请求内容时调用(内容开始加载) -> view的过渡动画可在此方法中加载 - (void)webView:(WKWebView *)webView didCommitNavigation:( WKNavigation *)navigation { NSLog(@"内容返回时调用,得到请求内容时调用。 4"); } //页面加载完成时调用 - (void)webView:(WKWebView *)webView didFinishNavigation:( WKNavigation *)navigation { NSLog(@"页面加载完成时调用。 5"); } //请求失败时调用 - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error { NSLog(@"error1:%@",error); } -(void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error { NSLog(@"error2:%@",error); } //在请求发送之前,决定是否跳转 -> 该方法如果不实现,系统默认跳转。如果实现该方法,则需要设置允许跳转,不设置则报错。 //该方法执行在加载界面之前 //Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Completion handler passed to -[ViewController webView:decidePolicyForNavigationAction:decisionHandler:] was not called' - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { //允许跳转 decisionHandler(WKNavigationActionPolicyAllow); //不允许跳转 // decisionHandler(WKNavigationActionPolicyCancel); NSLog(@"在请求发送之前,决定是否跳转。 1"); } //在收到响应后,决定是否跳转(同上) //该方法执行在内容返回之前 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler { //允许跳转 decisionHandler(WKNavigationResponsePolicyAllow); //不允许跳转 // decisionHandler(WKNavigationResponsePolicyCancel); NSLog(@"在收到响应后,决定是否跳转。 3"); } //接收到服务器跳转请求之后调用 - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation { NSLog(@"接收到服务器跳转请求之后调用"); } -(void)webViewWebContentProcessDidTerminate:(WKWebView *)webView { NSLog(@"webViewWebContentProcessDidTerminate"); }
这方面包括:创建新的WebView、界面弹出提示框
创建新的WebView
1 2 // 创建一个新的WebView - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;
界面弹出提示框
系统提供了三种弹出提示框的方法:警告框、确认框、输入框
直接查看代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 //警告框 /** webView界面中有弹出警告框时调用 @param webView web视图调用委托方法 @param message 警告框提示内容 @param frame 主窗口 @param completionHandler 警告框消失调用 */ - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler { completionHandler(); NSLog(@"警告框"); } //输入框 /** web界面中弹出输入框时调用 @param webView web视图调用委托方法 @param prompt 输入消息的显示 @param defaultText 初始化时显示的输入文本 @param frame 主窗口 @param completionHandler 输入结束后调用 */ -(void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler { NSLog(@"输入框"); completionHandler(@"http"); } //确认框 /** 显示一个JavaScript确认面板 @param webView web视图调用委托方法 @param message 显示的信息 @param frame 主窗口 @param completionHandler 确认后完成处理程序调用 */ -(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler { NSLog(@"确认框"); completionHandler(YES); }
以上就是WKWebView基本使用方法,其他的不做扩展和补充。也许以后再深入研究时,会有不一样的看法,到时再做推翻或补充。
以下是个人的一点看法
WKWebView
是在iOS8之后出现的新的网页加载控件,将来也必将取代UIWebView
,这是毋庸置疑的事情。
关于项目优化方面:其实很多人建议在项目中添加WKWebView
去替代UIWebView
。以未来的发展趋势来看,这点无可厚非。
我下面想说的是站在老项目并且其中内嵌网页比较多的立场的,iOS8以上使用WKWebView
,iOS8以下使用UIWebView
。这是目前解决方案的好办法。但维护和优化都需要成本,时间也是成本的一部分。
这里附上demo一份:WKWebView代码
这里给出几个讲解WKWebView
的链接,对我帮助很大:
WKWebView的新特性与使用
使用WKWebView替换UIWebView
UIWebView、WKWebView使用详解及性能分析
WKWebView学习笔记