WKWebView 和本地代码交互方式

来源:互联网 发布:铁三角msr7煲机 知乎 编辑:程序博客网 时间:2024/06/05 16:58

从iOS 8.0开始,应该使用WKWebView。

消息交互

这里写图片描述

WKWebView和本地程序的交互有3种方式:

第一种在WebView内容的特定加载阶段执行一段JS。
WKWebViewconfigurationusercontentController中添加一个WKUserScript。使用WKUserContentControlleraddUserScript方法,这个方法中可以指定JS代码执行的时机,目前只有WKUserScriptInjectionTimeAtDocumentStartWKUserScriptInjectionTimeAtDocumentEnd两个选项。

NSString *jsCode = @"var s = document.createElement('style');"    "s.textContent = '"    "body { font-size: 40px;}; '"    "\n"    "document.documentElement.appendChild(s);\n";WKUserScript *script = [[WKUserScript alloc] initWithSource:jsCodeinjectionTime:WKUserScriptInjectionTimeAtDocumentStartforMainFrameOnly:YES];WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];config.userContentController = [[WKUserContentController alloc] init];[config.userContentController addUserScript:script];[config.userContentController addScriptMessageHandler: self name:@"playbutton”];

第二种方式是在任何时候,本地代码让WKWebView执行一段JS。
直接在WKWebView上执行evaluateJavaScript:completionHandler

NSString *jsCode = @"var s = document.createElement('style');"    "s.textContent = '"    "body { font-size: 40px;}; '"    "\n"    "document.documentElement.appendChild(s);\n";[self.webView evaluateJavaScript:jsCode completionHandler:^(id _Nullable, NSError * _Nullable error) {}];

第三种是WKWebView中HTML上执行JS代码向本地发送消息。
在WKWebView的configuration的usercontentController中添加一个id<WKScriptMessageHandler>。这是一个实现了WKScriptMessageHandler接口的对象,这个接口只有一个方法:userContentController:didReceiveScriptMessage:这个方法用于处理JS发送的消息。

HTML 中的代码如下:

<button style="width: 100px; height: 30px" onclick="window.webkit.messageHandlers.playbutton.postMessage('play')">点击</button>

id<WKScriptMessageHandler>接口实现:

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{    NSLog(@"name: %@ content: %@",  message.name, message.body);}

导航控制

这里写图片描述

和导航相关的API在WKWebView本身的接口和navigationDelegate上。

1.在WKWebView上有一个属性是loading,指示web内容是否在加载中,可以通过KVO的方式来获取加载完成事件。一般可以用来显示或者影藏loading的indicator。

[self.webView addObserver:self forKeyPath:@"loading"                      options:NSKeyValueObservingOptionNew context:nil];

2.WKWebView本身的goBackgoForwardgoToBackForwardListItem可以被直接用来导航。

3.通过navigationDelegate来控制导航。

- (void)webView:(WKWebView *)webViewdecidePolicyForNavigationAction:(WKNavigationAction *)navigationAction        decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {    //在跳转之前决定是否要继续    NSLog(@"decidePolicyForNavigationAction");    if(navigationAction.navigationType == WKNavigationTypeLinkActivated){        NSURL *url = navigationAction.request.URL;        NSLog(@"will goto %@", url);    }    decisionHandler(WKNavigationActionPolicyAllow);}-(void)webView:(WKWebView *)webViewdecidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponsedecisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{    //获取到response的Meta之后决定是否要继续    NSLog(@"decidePolicyForNavigationResponse");//    NSLog(@"%@", navigationResponse.response.MIMEType);    decisionHandler(WKNavigationResponsePolicyAllow);}-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{    NSLog(@"didFinishNavigation");}...

navigationDeleagate的接口会在导航的对应阶段被调用,让接口的实现者来决定是否要继续导航,或者在这个时候做些别的事情。
被调用的顺序是:

2017-07-27 21:27:58.375656+0800 WebView[4978:1060161] decidePolicyForNavigationAction2017-07-27 21:27:58.377185+0800 WebView[4978:1060161] didStartProvisionalNavigation2017-07-27 21:27:58.480193+0800 WebView[4978:1060161] decidePolicyForNavigationResponse2017-07-27 21:27:58.488432+0800 WebView[4978:1060161] didCommitNavigation2017-07-27 21:27:58.670341+0800 WebView[4978:1060161] didFinishNavigation

参考文献

官方文档

阅读全文
0 0
原创粉丝点击