摘自一篇有用的WKWebView的JS交互文章

来源:互联网 时间:2017-01-22

优点:WebKit 使用Nitro JavaScript引擎,webview可以和Safari加载一样快。加载网页占用的内存大大优化。高达60fps的滚动刷新频率及内置手势。开放了更多API给开发者(14个类、3个协议);

使用:首先引入库 

#import  <WebKit/WebKit.h>

初始化:WKWebViewConfiguration class wkwebview的基本配置类 

    WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc]init]; 先实例化配置类 以前UIWebView的属性有的放到了这里

   _wkwebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0.0f, screen_width, screen_height) configuration:configuration];


新的属性:

    _wkwebView.allowsBackForwardNavigationGestures =YES;//打开网页间的滑动返回

    _wkwebView.allowsLinkPreview = YES;//允许预览链接

        backForwardList 中包含backList(访问过未返回的地址) forwardList(访问过已返回的地址)currentItem(当前访问的地址)


   wkwebview提供了KVO属性 可以用来获取加载进度(estimatedProgress) URL(URL)、TITLE(title)是否变化、是否可以前进或后退

    [_wkwebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];//注册observer拿到加载进度


wkwebview除了后退:goBack 前进: goForward 方法外 还提供了reload方法 刷新当前页面 以及stopLoading 停止刷新

加载h5页面和UIWebView相似:[_wkwebView loadRequest:[NSURLRequest requestWithURL:url]];

代理:


//WKNavigationDelegate


//发送请求前决定是否允许跳转

/*

 typedef NS_ENUM(NSInteger, WKNavigationActionPolicy) {

 WKNavigationActionPolicyCancel,不允许

 WKNavigationActionPolicyAllow, 允许

 } NS_ENUM_AVAILABLE(10_10, 8_0);

 */

发生请求前是否允许跳转

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler

{

    decisionHandler(WKNavigationActionPolicyAllow);

    NSLog(@"发送请求前 allow跳转");

}


//接收到服务器响应后决定是否允许跳转

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;

{

    decisionHandler(WKNavigationResponsePolicyAllow);

    NSLog(@"接收到响应后 allow跳转");


}


//接收到服务器跳转响应后调用

-(void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation

{

    NSLog(@"tiaozhuan");


}


//开始加载页面

-(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation;

{

    NSLog(@"开始加载页面");

}


//加载页面数据完成

-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation

{

    NSLog(@"加载页面完成");

    NSLog(@"backlist ===%@",webView.backForwardList.backList);访问过未返回的页面

    NSLog(@"forwordlst==%@",webView.backForwardList.forwardList);访问过已返回的页面

    NSLog(@“url===%@",webView.backForwardList.currentItem.URL);当前访问的页面

    在这里可以拿到web页的相关信息 做一些操作   

}


//接收数据

-(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation

{

    NSLog(@"接收数据中");

}


//加载失败

- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error;

{

    NSLog(@"页面加载失败");

}

//在这个方法里实现注册的供js调用的oc方法

-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message

{

      js native 交互

}


WKUIDelegate 页面中有调用了js的alert、confirm、prompt方法,应该实现下面这几个代理方法,然后在原来这里调用native的弹出窗,因为使用WKWebView后,HTML中的alert、confirm、prompt方法调用是不会再弹出窗口了,只是转化成ios的native回调代理方法(没咋用)。


JS NATIVE 交互:wkwebview提供了API实现js交互 不需要借助JavaScriptCore或者webJavaScriptBridge。使用WKUserContentController实现js native交互

oc代码:

 首先需要在实例化WKWebViewConfiguration时 实例 WKUserContentController类并将其赋值给confiuration的属性:userContentController。

WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc]init];

    //注册供js调用的方法

    userContentController =[[WKUserContentController alloc]init];

    [userContentController addScriptMessageHandler:self  name:@“aaa”];//注册一个name为aaa的js方法

    configuration.userContentController = userContentController;

    configuration.preferences.javaScriptEnabled = YES;打开JavaScript交互 默认为YES

    _wkwebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0.0f, screen_width, screen_height) configuration:configuration];

实现WKScriptMessageHandler的协议方法

-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message

{

userContentController 注册message的WKUserContentController;

message:js传过来的数据

id body:消息携带的信息 Allowed types are NSNumber, NSString, NSDate, NSArray, NSDictionary, and NSNull.

NSString *name:消息的名字 如aaa

 //message.name  js发送的方法名称

    if([message.name  isEqualToString:@"aaa"])

    {

        NSString * body = [message.body objectForKey:@“body"];

     在这里写oc 实现协议的native方法 }

}



前端h5代码:前端需要用 window.webkit.messageHandlers.注册的方法名.postMessage({body:传输的数据} 来给native发送消息

例如:

function secondClick() {

    window.webkit.messageHandlers.aaa.postMessage({body: 'call js alert in js'});

}


**重要 如果注册了方法    [userContentController addScriptMessageHandler:self  name:@“aaa"];

会导致hangler一直被引用 导致不走Delloc web页面无法释放 所以要在-(void)viewDidDisappear:(BOOL)animated中将messageHandler移除

    [userContentController removeScriptMessageHandlerForName:@“aaa"]; 关闭web页时会释放内存。

相关阅读:
Top