美文网首页
WKWebView与原生的交互以及代理方法

WKWebView与原生的交互以及代理方法

作者: huicuihui | 来源:发表于2017-12-19 17:30 被阅读31次

项目里面很多地方都是用的h5, h5的处理都放在了一个新的控制器里面,里面很多代理方法,在这里记录一下。
很多h5的处理,iOS和js的交互都要通过代理方法去处理。
1、iOS调用js的方法, 例如调用js的跳转方法。
2、iOS获取js的方法,截取方法然后自己去实现。

@protocol WKScriptMessageHandler <NSObject>

@required

/*! @abstract Invoked when a script message is received from a webpage.
 @param userContentController The user content controller invoking the
 delegate method.
 @param message The script message received.
 */
方法中主要是收到JS的回执脚本就会运行一次
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;

@end

该代理方法是h5调用js方法的时候,客户端可以获取到并且去做自己的处理。
点击某个按钮,webview加载完成之后原生可以获取到里面的某些需要的数据去设置。
h5调原生本地函数

/**
 当从网页收到脚本消息时调用。

 @param userContentController 调用委托方法的用户内容控制器。
 @param message 收到的脚本消息。
 */
- (void)userContentController:(WKUserContentController *)userContentController
      didReceiveScriptMessage:(WKScriptMessage *)message {
    
    NSDictionary *bodyParam = (NSDictionary*)message.body;
    NSString *func = [bodyParam objectForKey:@"function"];
    
    NSLog(@"MessageHandler Name:%@", message.name);
    NSLog(@"MessageHandler Body:%@", message.body);
    NSLog(@"MessageHandler Function:%@",func);
    
    //本人喜欢只定义一个MessageHandler协议 当然可以定义其他MessageHandler协议
    
    if ([message.name isEqualToString:@"Native"])
    {
        NSDictionary *parameters = [bodyParam objectForKey:@"parameters"];
        //调用本地函数
        if([func isEqualToString:@"modifySuccess"])
        {
            NSLog(@"在这里面去做弹窗提示,为视图设置数据,调用原生的返回等操作");
        }
        else if([func isEqualToString:@"callNativeHomePageBack"])
        {
            NSLog(@"在这里面去做弹窗提示,为视图设置数据,调用原生的返回等操作");
        }
        else if ([func isEqualToString:@"callNativeWebShare"]){
            NSLog(@"调用原生的分享功能");
        }
        else if ([func isEqualToString:@"callNativeWebLoginView"]){
            NSLog(@"跳转到登录页面");
        }
        else if ([func isEqualToString:@"callNativeWebPageShare"]){
            NSLog(@"弹出本地的分享菜单");
        }
        else if ([func isEqualToString:@"callNativeProduct"]){
            NSLog(@"点击立即购买按钮,去购买操作");
        }
        else if ([func isEqualToString:@"keyboardBarShow"]){
            NSLog(@"web要求评论条出现");
        }
        else if ([func isEqualToString:@"keyboardBarHide"]){
            NSLog(@"web要求评论条消失");
        }
        else if ([func isEqualToString:@"callNativeWebviewWithURL"]){
            NSLog(@"跳出新浏览器,创建一个webview去显示新页面");
        }
        else if ([func isEqualToString:@"callNativeWebviewWithURLWithNaviBar"]){
            NSLog(@"跳出新浏览器");
        }
        else if ([func isEqualToString:@"keyboardBarShowUpdateCommentCount"]){
            NSLog(@"刷新评论的数据");
        }
    }
}

这个是检测收到html的js消息的时候, 我们客户端做的操作。
上面的就是收到html的修改用户信息、分享、点击客服、收藏等消息。

原生调用js方法

例:
文章详情页面发表评论功能,发评论的内容是客户端控制的,客户端才拥有。
点击发送按钮,需要调用js方法,告诉h5发表评论的内容。
点击发送按钮需要调用h5的js方法:

NSString *contentString = [<#评论的内容#> stringByReplacingOccurrencesOfString:@"\n" withString:@"<br/>"];

[wkWebView evaluateJavaScript:[NSString stringWithFormat:@"keyboardBarCommentReturn('%@')",contentString] completionHandler:^(id _Nullable response, NSError * _Nullable error){
        
    }];

例二:
点击底部的评论按钮,详情页滚动到评论,需要h5去做,原生告诉h5

[wkWebView evaluateJavaScript:[NSString stringWithFormat:@"keyboardBarRecordReturn('1')"] completionHandler:^(id _Nullable response, NSError * _Nullable error) {

    }];
代理方法

WKUIDelegate

- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
    NSLog(@"%s", __FUNCTION__);
    
    [self.wkWebview loadRequest:[self fixRequest:navigationAction.request]];
    return webView;
}


- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
    
    NSLog(@"%s", __FUNCTION__);
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }]];
    
    [self presentViewController:alert animated:YES completion:NULL];
}

- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler{
    
    NSLog(@"%s", __FUNCTION__);
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"confirm" message:@"JS调用confirm" preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(YES);
    }]];
    [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(NO);
    }]];
    [self presentViewController:alert animated:YES completion:NULL];
    
    NSLog(@"%@", message);
}

- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler{
    
    NSLog(@"%s", __FUNCTION__);
    NSLog(@"%@", prompt);
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"textinput" message:@"JS调用输入框" preferredStyle:UIAlertControllerStyleAlert];
    [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.textColor = [UIColor redColor];
    }];
    
    [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler([[alert.textFields lastObject] text]);
    }]];
    
    [self presentViewController:alert animated:YES completion:NULL];

}

上面的那个是WKUIDelegate, 可以检测到js到弹窗, 然后我们出来我们自己的样式。弹出什么和做什么操作。

WKNavigationDelegate

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    NSLog(@"%s", __FUNCTION__);
    
    NSURLRequest *originalRequest = navigationAction.request;
    [self fixRequest:originalRequest];
    [webView evaluateJavaScript:[self jsString:navigationAction.request.URL.absoluteString] completionHandler:^(id _Nullable response, NSError * _Nullable error) {
        if (error == nil) {
            NSLog(@"成功注入");
        }
    }];
    decisionHandler(WKNavigationActionPolicyAllow);

}

//可以在该代理方法中 获取头部信息 包括过期日期 修改日期等
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
    NSLog(@"%s", __FUNCTION__);
    
    NSString *cacheControl = [(NSHTTPURLResponse*)navigationResponse.response allHeaderFields][@"Cache-Control"]; // max-age, must-revalidate, no-cache
    NSArray *cacheControlEntities = [cacheControl componentsSeparatedByString:@","];

    for(NSString *substring in cacheControlEntities) {
        
        if([substring rangeOfString:@"max-age"].location != NSNotFound) {
            
            // do some processing to calculate expiresOn
            NSString *maxAge = nil;
            NSArray *array = [substring componentsSeparatedByString:@"="];
            if([array count] > 1)
                maxAge = array[1];
            
           NSDate * expiresOnDate = [[NSDate date] dateByAddingTimeInterval:[maxAge intValue]];

        //保存过期时间
            [[NSUserDefaults standardUserDefaults] setObject:expiresOnDate forKey:kHtml_gqsj];

        }
    }

    decisionHandler(WKNavigationResponsePolicyAllow);
    
}

//请求开始的代理方法
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
{
}
//请求结束的代理方法。
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation{
    NSLog(@"%s", __FUNCTION__);

}

- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error{
    NSLog(@"%s", __FUNCTION__);

}

相关文章

网友评论

      本文标题:WKWebView与原生的交互以及代理方法

      本文链接:https://www.haomeiwen.com/subject/arkiwxtx.html