• h5(WKWebView)和iOS之间的交互问题


           目前,大多数的应用中都嵌入了H5。那么在iOS应用中如何嵌入一个H5,并且和它进行交互就成了

    一个势必要掌握的技术了。本文我将结合我在项目中的一些需求整理出对应的技术点,仅供参考。

          在iOS开发中,H5的嵌入可以通过UIWebView或者WKWebView。这两个都是继承UIView,来加载web数据的类。

    UIWebView是在iOS2的时候开始使用的。特点是加载速度慢,占用内存多,优化艰难。WKWebView是在iOS8苹果

    新推出的,加载速度快,占用内存较少,是一个不错的选择。如果想要比较两者的区别,您可以选择一个网页进行

    测试一下。鉴上所述,我们选择WKWebView进行开发。

    • WKWebView的创建
    - (void)createWebView{
    
              WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    
              // 根据需要去设置对应的属性
    
              WKWebView *webView = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:config];
    
              webView.navigationDelegate = self;
    
              [self.view addSubview:webView];  
    
              NSURL *url = [NSURL URLWithString:self.strURL];
    
              [self loadWebViewWithURL:url];   // JS调用OC 添加处理脚本
    
              [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"Share"];
    
        }

     

    • JS调用OC代码
      [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"Share"];

      这是利用WKWebView的一个新特性MessageHandler来处理JS调用原生方法。要实现JS调用iOS原生方法,步骤见下。

    • 添加<WKScriptMessageHandler>协议。让控制器成为MessageHandler的代理对象。

    • 对于监听的方法名要和JS开发的人商量好。这里我们监听的是Share方法,对于JS开发的人员必须要以以下方式写。

     window.webkit.messageHandlers. Share.postMessage(null)
    • 实现协议方法。在这个方法里message参数有一个属性body。message.body就是JS传过来的参数,可以是字符串,可以是数组,也可以是字典。通过message.name判断可以知道监听的是JS的哪个方法。

    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
    
    {    
    
        if ([message.name isEqualToString:@"Share"]) {
    
                 //TODO
    
        }
    
    }

        至此,JS调用OC代码就已完结。是不是很简单。另外,我在网上也看到了不一样的处理方式。大家可以参考WebViewJavascriptBridge我觉得写的比较清楚。

    • OC调用JS代码
        [self.webView evaluateJavaScript:@"show()" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
    
                    //TODO
    
          }];

    相信代码已经看得很清楚啦。show()就是JS写的方法,这个方法可传可不传参数,具体依实际情况而定。另外关于UIWebView和JS的交互,以下部分仅供参考。

        JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    
        context[@"Share"] = ^() {
    
            NSArray *args = [JSContext currentArguments];
    
            dispatch_async(dispatch_get_main_queue(), ^{
    
                    //TODO
    
            });
    • 关于<WKNavigationDelegate>

         网页加载开始,结束,失败这几个都特别简单,我就不赘述了。说一下下面这个协议方法,这个方法发生在页面跳转中。WKNavigationActionPolicy是一个枚举,

      WKNavigationActionPolicyAllow表示允许跳转,WKNavigationActionPolicyCancel表示取消跳转。对了,这里还有一个补充: scrollView嵌套网页和原生view,原生view要根据网页的高度来布局

    我看到不少的电商应用都有这种布局,但在算高度上会有各种问题,不知道你们有遇见过?

    - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
    
    {
    
        NSString *url = navigationAction.request.URL.absoluteString;
    
        if(![url isEqualToString:self.strURL]) {
    
              // 页面跳转
    
        }
    
        decisionHandler(WKNavigationActionPolicyAllow);
    
    }
    • 关于< WKUIDelegate >

       不知道您有没有遇见过JS写的alert()框在iOS上不弹出。那么您有没有实现这些协议方法呢。

    /// 创建一个新的WebView
    
    - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;
    
    /// 输入框
    
    - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler;
    
    /// 确认框
    
    - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler;
    
    /// 警告框
    
    - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;
    •  获取网页标题,网页加载进度和加载状态

         这是通过KVO的方式进行监听的。您可以点击进WKWebView的内部看一下,他们每个属性上面都有很长的解释,你不难发现这一段。举一个获取标题的例子。

      其他的类似。别忘了,KVO监听在dealloc中移除监听者哦。

        [self.webView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL];
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
    
    {  
    
        if ([keyPath isEqualToString:@"title"]) {
    
            if (object == self.webView) {
    
                if(self.navigationController) 
    
                    self.navigationItem.title = self.webView.title;
    
            }
    
        }
    
        else {
    
            [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    
        }
    
    }
  • 相关阅读:
    windows 7 codepage id name 名称
    最大团
    三分的多种写法及对应的精度 三分套三分原理
    AC自动机
    c++ queue
    lca 欧拉序+rmq(st) 欧拉序+rmq(线段树) 离线dfs 倍增
    node *p,*q
    dfs序和欧拉序
    P3861 8月月赛A
    洛谷P3862 8月月赛B
  • 原文地址:https://www.cnblogs.com/liu-lang/p/7121656.html
Copyright © 2020-2023  润新知