一、WKWebView 的基本使用
- 初始化方法
- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration - 简单介绍一下 configuration,WKWebViewConfiguration 里面有个 userContentController。可通过它为 webview 注入 javaScript 代码。并且可以添加监听 javaScript 的回调。
(1)初始化 configurationWKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc]init];
(2)获取 javaScript 代码,我把 javaScript 代码写在了一个文件中NSString *jsStr = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"WKWebViewJS" ofType:@"js"] encoding:NSUTF8StringEncoding error:nil];
(3)初始化 script 对象
1 | /*@abstract 初始script对象 |
2 | @param source javaScript代码 |
3 | @param injectionTime 注入javaScript代码的时机 |
4 | @param forMainFrameOnly 是不是仅为MainFrame注入 |
5 | */ |
6 | WKUserScript *userScript = [[WKUserScript alloc]initWithSource:jsStr injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO]; |
(4)添加 script 对象[configuration.userContentController addUserScript:userScript];
(5)添加 scriptMessage 回调[configuration.userContentController addScriptMessageHandler:self name:@"imageClick"]; [configuration.userContentController addScriptMessageHandler:self name:@"popToPreviousVC"];
若添加过回调之后,在结束调用这个方法window.webkit.messageHandlers.<handleName>.postMessage(<messageBody>) 系统会调用这个方法- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
- WKWebView 执行 javaScript 代码
self.webview evaluateJavaScript:@"changeFontSize(12)" completionHandler:^(id _Nullable result, NSError * _Nullable error) { }]; - WKWebView 的一些简单属性的介绍
1 | backForwardList 浏览历史 |
2 | title 网页标题 支持KVO |
3 | URL 正在显示的URL 支持KVO |
4 | loading 是否正在加载 支持KVO |
5 | estimatedProgress 加载进度 支持KVO |
6 | canGoBack canGoForward 能否后退 前进 支持KVO |
7 | reload 重新加载 |
8 | stopLoading 停止加载 |
9 | allowsBackForwardNavigationGestures 是否允许侧滑返回上一页 |
5、WKWebView 的加载方法跟 UIWebView 基本一样
1 | - (nullable WKNavigation *)loadRequest:(NSURLRequest *)request; |
2 | - (nullable WKNavigation *)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL; |
3 | - (nullable WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL; |
#二 WKWebViewUIDelegate
1 | //当需要打开一个新窗口的时候的调用,如a标签的target='_blank',需要返回一个新的Webview |
2 | - (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures |
3 | 以下三个类似alert的代理,一定要调用completionHandler(),这个回调,告诉webview结果 |
4 | //webview上需要弹出alert的时候调用此方法,如果不实现此方法,则webview的alert是显示不出来,alert类似于只有确定按钮的UIAlertView |
5 | - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler |
6 | //webview上需要弹出confirm的时候调用此方法,如果不实现此方法,则webview的confirm是显示不出来,confirm类似于有确定按钮和取消按钮的UIAlertView |
7 | - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler |
8 | webview上需要弹出prompt的时候调用此方法,如果不实现此方法,则webview的prompt是显示不出来,prompt类似于带一个textField的UIAlertView。defaultText相当于textField的placeholed |
9 | - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler |
10 | //window.close() 的时候调用 |
11 | - (void)webViewDidClose:(WKWebView *)webView |
#三 WKWebViewNavigationDelegate
1 | //决定是否允许发起这个请求 |
2 | - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler |
3 | //在webview有响应之后,再次决定是否允许这个请求 |
4 | - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandle |
5 | //webview开始加载的时候调用 |
6 | - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation |
7 | //webview内容已经加载结束,但是上面的某些资源比如图片加载之前调用 |
8 | - (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation |
9 | //webview加载结束的时候调用 |
10 | - (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation |
11 | //webview加载失败的时候调用 |
12 | - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error |
13 | //webview在commit过程中失败的时候调用,例如在didCommitNavigation这个代理方法中调用webview的stopLoading方法 |
14 | - (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error |
#四 WKScriptMessageHandler
1 | //收到JavaScript回调的时候调用 |
2 | - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message |
#五 接下来用一下做个小 demo。
功能如下:
1、点击按钮可以控制 webView 上的字体的大小和颜色
2、点击 webView 上的返回,能 pop 到上一个 VC
3、点击 webView 图片,弹出 alert 告诉我弹出的是第几张图片,和图片的大小和位置以及所有的图片的地址
4、验证代理方法
效果如下:

(1)首先为 webview 注入 JS 代码,JS 代码里主要实现的是:当 window 加载之后,为 img 标签添加 click 事件,定义改变字体颜色和大小的函数
1 | WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc]init]; |
2 | NSString *jsStr = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"WKWebViewJS" ofType:@"js"] encoding:NSUTF8StringEncoding error:nil]; |
3 | WKUserScript *userScript = [[WKUserScript alloc]initWithSource:jsStr injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO]; |
4 | [configuration.userContentController addUserScript:userScript]; |
5 | [configuration.userContentController addScriptMessageHandler:self name:@"imageClick"]; |
6 | [configuration.userContentController addScriptMessageHandler:self name:@"popToPreviousVC"]; |
(2)调用 JS 代码,实现改变字体颜色和大小
1 | - (void)runJavaAcript:(UIButton *)button{ |
2 | if (button.tag == 0) { |
3 | [self.webview evaluateJavaScript:@"changeTextColor('#f00')" completionHandler:^(id _Nullable result, NSError * _Nullable error) { |
4 | }]; |
5 | }else if (button.tag == 1){ |
6 | [self.webview evaluateJavaScript:@"changeTextColor('#666')" completionHandler:^(id _Nullable result, NSError * _Nullable error) { |
7 | }]; |
8 | }else if (button.tag == 2){ |
9 | [self.webview evaluateJavaScript:@"changeFontSize(38)" completionHandler:^(id _Nullable result, NSError * _Nullable error) { |
10 | }]; |
11 | }else if (button.tag == 3){ |
12 | [self.webview evaluateJavaScript:@"changeFontSize(12)" completionHandler:^(id _Nullable result, NSError * _Nullable error) { |
13 | }]; |
14 | } |
15 | } |
(3)点击 webview 上的返回按钮 pop 到上一个 VC
1)在 html 中的定义
1 | //返回标签的定义 |
2 | <button onclick="popToPreviousVC()">返回</button> |
3 | //函数实现 |
4 | function popToPreviousVC(){ |
5 | webkit.messageHandlers.popToPreviousVC.postMessage(true); |
6 | } |
2)webview 收到回调的处理
1 | - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{ |
2 | if ([message.name isEqualToString:@"imageClick"]) { |
3 | NSInteger current = [message.body[@"current"] integerValue]; |
4 | UIAlertView *alert = [[UIAlertView alloc]initWithTitle:[NSString stringWithFormat:@"你点击了第%ld张图片,该图片的坐标是%@",(long)current,message.body[@"rect"]] message:[NSString stringWithFormat:@"图片的地址分别是:%@",message.body[@"srcs"]] delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil]; |
5 | [alert show]; |
6 | }else if([message.name isEqualToString:@"popToPreviousVC"]){ |
7 | [self.navigationController popViewControllerAnimated:YES]; |
8 | } |
9 | } |
要想接收到回调,一定要先在先添加回调,而且添加的名字一定要和发送的名字一致[configuration.userContentController addScriptMessageHandler:self name:@"popToPreviousVC"];
(4)点击 webView 图片,弹出 alert 告诉我弹出的是第几张图片,和图片的大小和位置以及所有的图片的地址,回调的信息如上,下面展示 js 代码
1 | function initImageClick(obj,index) { |
2 | obj.onclick = function imgOnclick() { |
3 | //获取image的位置 |
4 | var rect = obj.getBoundingClientRect(); |
5 | //获取所有的img标签 |
6 | var imgs = document.getElementsByTagName('img'); |
7 | var srcs = new Array(); |
8 | for(var i in imgs){ |
9 | //判断img的src是否为未定义,加入srcs数组 |
10 | if(imgs[i].src != undefined) |
11 | srcs.push(imgs[i].src); |
12 | } |
13 | //由于OC不识别rect这个对象,在这把rect转成了符合CGRect格式的字符串 |
14 | var message = {'rect':'{{'+rect.left+', '+rect.top+'}, {'+rect.width+', '+rect.height+'}}}'}; |
15 | //为message这个js对象的属性赋值 |
16 | message.current = index; |
17 | message.srcs = srcs; |
18 | //发送消息 |
19 | webkit.messageHandlers.imageClick.postMessage(message); |
20 | } |
21 | } |
代理方法的验证具体看demo