美文网首页
iOS WKWebView JS 与 原生交互小结

iOS WKWebView JS 与 原生交互小结

作者: Superman168 | 来源:发表于2021-05-10 17:01 被阅读0次

前言

目前iOS项目中 Webview 几乎都会用到,iOS 8 之前使用UIWebView,iOS 8 之后 Apple 就不推荐使用了,目前已经放弃了,如果项目中存在就无法上架了,需要转为WKWebView了,说实话 UIWebView 是有性能上的缺陷,内存优化不够友好等,但是不得不说这是老的iOS开发人员用的最熟练熟悉的了,用起来得心应手。非迫不得已还真不愿转到WKWebView。好吧,既然已经这样了,又何必苦苦单恋一支花呢?

看了网上教程很多,自己使用小结一下,简单易用,本文适用于菜鸟级开发,废话不说了,

本地 html 文件,如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body style="margin: 24px">
    <p style="text-align:center;text-indent:2em;">
        <span style="color:#333333;font-size:18px;font-family:PingFang SC Semibold;"><strong>Demo演示说明</strong></span>
    </p>
    <span style="color:#666666;font-size:14px;font-family:SimHei;">测试内容。</span><br />
    <br />
    <span style="color:#666666;font-size:14px;font-family:SimHei;">如您同意</span>
    <span style="color:#4F91FF;font-size:14px;font-family:SimHei;"><strong onclick="jumpUserProtocol()">《用户协议》</strong>
        <span style="color:#000000;">、</span>
        <span style="color:#666666;"></span></span><span style="color:#4F91FF;font-size:14px;font-family:SimHei;"><strong onclick="jumpPrivacyPolicy()">《隐私政策》</strong></span>
    <span style="color:#666666;font-size:14px;font-family:SimHei;">,请点击“继续使用”开始使用我们的产品和服务。</span><span style="color:#666666;"></span>
    <p>
        <br />
    </p>
    
    <script type="text/javascript">

        function jumpUserProtocol() {
            window.webkit.messageHandlers.jumpUserProtocol.postMessage("UserProtocol");
        }
        function jumpPrivacyPolicy(){
            window.webkit.messageHandlers.jumpPrivacyPolicy.postMessage("PrivacyPolicy");
        }
    
        function callJS(message) {
            alert(message);
            window.webkit.messageHandlers.jumpPrivacyPolicy.postMessage("PrivacyPolicy");            
        }
            
    </script>
</body>
</html>

最主要的方法:发送消息

window.webkit.messageHandlers.<#对象名#>.postMessage(<#参数#>)

发送消息

注意:对象名和方法名jumpUserProtocol名字的一致,参数可以是常用的NSArray,NSDictionary等类型,先说下在这个Demo中其实没用上,用的方法名判断的。

WKWebView 创建

#pragma mark ========= lazy load =========
-(WKWebView *)webView {
    if (!_webView) {
        // 2. 网页JS调原生:
        //   1> 需要先设置 Webview.configuration 的 userContentController
        //   2> 注册方法名 [wkUController addScriptMessageHandler:self name:];
        //   3> 遵守协议<WKScriptMessageHandler>,实现其方法.
        //   4> 在控制器销毁时,需要移除方法名注册

        /*! 设置网页的配置文件 */
        WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
        /*! 允许视频播放 */
        configuration.allowsAirPlayForMediaPlayback = YES;
        /*! 允许在线播放 */
        configuration.allowsInlineMediaPlayback = YES;
        /*! 允许可以与网页交互,选择视图 */
        configuration.selectionGranularity = YES;
        /*! web内容处理池 */
        configuration.processPool = [[WKProcessPool alloc] init];
        /*! 自定义配置,一般用于 js调用oc方法(OC拦截URL中的数据做自定义操作) */
        WKUserContentController *wkUController = [[WKUserContentController alloc] init];
        /*! 自适应屏幕宽度,注入js */
        NSString *jSString = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width,user-scalable=no'); document.getElementsByTagName('head')[0].appendChild(meta); var lastDiv = document.createElement('div');lastDiv.id = 'last-div'; document.getElementsByTagName('body')[0].appendChild(lastDiv)";
        WKUserScript *wkUserScript = [[WKUserScript alloc] initWithSource:jSString injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
        [wkUController addUserScript:wkUserScript];
        /*! 允许用户更改网页的设置 */
        configuration.userContentController = wkUController;
        //JS调用OC 添加处理脚本
        [wkUController addScriptMessageHandler:self name:JSMessageName_Protocol];
        [wkUController addScriptMessageHandler:self name:JSMessageName_PrivacyPolicy];
        
        // 进行偏好设置
//        WKPreferences *preferences = [WKPreferences new];
//        preferences.javaScriptCanOpenWindowsAutomatically = YES;
//        preferences.minimumFontSize = 40.0;
//        configuration.preferences = preferences;
        
        CGRect frame = CGRectMake(0, 64, 375,600);
        _webView = [[WKWebView alloc] initWithFrame:frame configuration:configuration];
        _webView.navigationDelegate = self;
        _webView.scrollView.showsHorizontalScrollIndicator = NO;
//        _webView.scrollView.pagingEnabled = NO;
//        _webView.scrollView.bounces = NO;
        _webView.backgroundColor = [UIColor orangeColor];
    }
    return _webView;
}

注意: addScriptMessageHandler

//JS调用OC 添加处理脚本
[wkUController addScriptMessageHandler:self name:JSMessageName_Protocol];
[wkUController addScriptMessageHandler:self name:JSMessageName_PrivacyPolicy];

name为方法名 ,和JS 中的保持一致,添加脚本,相当于给Webview添加一个监听,有这个功能来处理JS。

加载本地 html 文件

// WKWebView 网页加载
    NSString* path = [[NSBundle mainBundle] pathForResource:@"UserPrivateInfo" ofType:@"html"];
    NSURL* url = [NSURL fileURLWithPath:path];
    NSURLRequest* request = [NSURLRequest requestWithURL:url] ;
    [self.webView loadRequest:request];

    [self.view addSubview:self.webView];

处理事件

在WKScriptMessageHandler代理方法中处理回调,实现自己的逻辑。


#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    
    if ([message.name isEqualToString:JSMessageName_Protocol]) {
        NSLog(@"********用户协议********");
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"用户协议js传递过来的参数"message:[NSString stringWithFormat:@"方法名:%@\n\n参数:%@",message.name,message.body] preferredStyle:UIAlertControllerStyleAlert];
        [alertController addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
            
        }]];
        [[[UIApplication sharedApplication] windows].firstObject.rootViewController presentViewController:alertController animated:YES completion:^{
            
        }];
    }else if ([message.name isEqualToString:JSMessageName_PrivacyPolicy]){
        NSLog(@"********隐私政策********");
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"隐私政策js传递过来的参数"message:[NSString stringWithFormat:@"方法名:%@\n\n参数:%@",message.name,message.body] preferredStyle:UIAlertControllerStyleAlert];
        [alertController addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
            
        }]];
        [[[UIApplication sharedApplication] windows].firstObject.rootViewController presentViewController:alertController animated:YES completion:^{
            
        }];
    }
}

上面就是JS调用OC原生实现。

OC调用JS

这个其实很简单,就一个方法:

#pragma mark -- 原生调用 JS
- (IBAction)callJS:(id)sender {
    // 1. webview调用JS函数, JS代码可根据需要拼接好。
    // 此处是设置需要调用的js方法以及将对应的参数传入,需要以字符串的形式
    // 带参数
    NSString *jsFounction = [NSString stringWithFormat:@"callJSFunc('%@')", @"UserProtocol"];
    // 不带参数
//    NSString *jsFounction = [NSString stringWithFormat:@"jumpUserProtocol()"];
    // 调用API方法
    [self.webView evaluateJavaScript:jsFounction completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        if (error) {
            NSLog(@"evaluateJavaScript:\n result = %@ error = %@",result, error);
        }else{
            NSLog(@"调用成功");
        }
    }];
}

相关文章

网友评论

      本文标题:iOS WKWebView JS 与 原生交互小结

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