zoukankan      html  css  js  c++  java
  • iOS中js调用oc获取返回值(WKWebView)

    https://blog.csdn.net/ljy_1024/article/details/92633698

    前言

    最近公司的APP需要进行hybrid模式的开发,即native和h5联合开发。此时前端工程师提到了一个需求,由前端调用native进行操作以及获取返回值。这样可以保证native只有一份代码,h5不用指定方法和native进行确认。为了实现这个需求,从网上的给出的解决办法来看,一种是使用原生的类和库方法,另外一种是使用第三方库。本文主要介绍使用原生类库进行操作。

    实现效果(demo)

    demo实现效果

    在实现效果图中,当前view是加载了wkwebview的实例,并且wkwebview加载了本地的html,界面上jsInvokeOC和invokeOCGetCookie是两个button。jsInvokeOC点击之后会调用native方法,而native方法又调用了js方法将结果异步传给html用于显示,也可以不进行显示直接在native中做相当的动作,比如返回上一级。下面的invokeOCGetCookie是直接调用的native,由native返回同步显示。

    实现

    1. 首先贴一下html和js代码,这样后面好叙述。
      test.html
    1.  
      <html>
    2.  
      <head>
    3.  
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    4.  
      <title>WebViewOCInvokeDemo</title>
    5.  
      <style>
    6.  
      *{
    7.  
      font-size: 50px;
    8.  
      }
    9.  
      .btn{height:80px; 60%; padding: 0px 30px; background-color: #0071E7; border: solid 1px #0071E7; border-radius:5px; font-size: 1em; color: white}
    10.  
      </style>
    11.  
      <script src="test.js"></script>
    12.  
       
    13.  
      </head>
    14.  
       
    15.  
      <body>
    16.  
      <div>
    17.  
      <button class="btn" type="button" onclick="jsInvokeOC()">jsInvokeOC</button>
    18.  
      <br />
    19.  
      <button class="btn" type="button" onclick="getCookie()">invokeOCGetCookie</button>
    20.  
      </div>
    21.  
      <br/>
    22.  
      <div id="cookie">Cookie's value</div>
    23.  
      <br/>
    24.  
      <div id="response">response's value</div>
    25.  
      </body>
    26.  
      </html>

    test.js

    1.  
      function jsInvokeOC() {
    2.  
      window.webkit.messageHandlers.jsInvokeOCMethod.postMessage('Javascript invoke OC');
    3.  
      }
    4.  
       
    5.  
      function getCookie() {
    6.  
      var cookie = window.prompt("getCookie");
    7.  
       
    8.  
      document.getElementById('cookie').innerText = "cookie: " + cookie;
    9.  
      }
    10.  
       
    11.  
      function response2JS(response) {
    12.  
      document.getElementById('response').innerText = "resp: " + response;
    13.  
      }
    1. 对于第一个按钮触发的方法是由下面这行代码调用的。
    window.webkit.messageHandlers.jsInvokeOCMethod.postMessage('Javascript invoke OC');
    

    该方法的的原型是:
    window.webkit.messageHandlers.<方法名>.postMessage(<消息内容>);
    <方法名>是和oc之间商量好的方法名,用于oc判断;
    <消息内容>用于发给oc的消息内容字符串。

    这种方法的实现需要WKWebViewConfiguration的WKUserContentController添加对<方法名>的消息监听,触发后在代理方法:

    1.  
      - (void)userContentController:(WKUserContentController *)userContentController
    2.  
      didReceiveScriptMessage:(WKScriptMessage *)message;

    中通过判断message.name获取<方法名>,通过message.body获取<消息内容>。
    实现代码如下:
    (1)配置WKUserContentController。

    1.  
      - (WKWebView*)webView {
    2.  
      if (!_webView) {
    3.  
      WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc]
    4.  
      init];
    5.  
       
    6.  
      _webView = [[WKWebView alloc] initWithFrame: CGRectZero
    7.  
      configuration: configuration];
    8.  
       
    9.  
      WKUserContentController* userCC = _webView.configuration.userContentController;
    10.  
       
    11.  
      [userCC addScriptMessageHandler: self
    12.  
      name: @"jsInvokeOCMethod"];
    13.  
       
    14.  
      _webView.UIDelegate = self;
    15.  
      _webView.navigationDelegate = self;
    16.  
      }
    17.  
       
    18.  
      return _webView;
    19.  
      }

    (2)实现回调方法。

    1.  
      #pragma mark - WKScriptMessageHandler
    2.  
      - (void)userContentController:(WKUserContentController *)userContentController
    3.  
      didReceiveScriptMessage:(WKScriptMessage *)message {
    4.  
      if ([message.name isEqualToString: @"jsInvokeOCMethod"]) {
    5.  
      NSLog(@"MessageBody: %@", message.body);
    6.  
       
    7.  
      // async return value
    8.  
      [self.webView evaluateJavaScript: @"response2JS('Hello return')"
    9.  
      completionHandler:^(id response, NSError * error) {
    10.  
      NSLog(@"response: %@, error: %@", response, error);
    11.  
      }];
    12.  
      }
    13.  
      }

    实现回调方法中调用了evaluateJavaScript是为了异步调用js方法来返回值,其中response2JS('Hello return')是js方法,在文件test.js中。
    当然此处可以不用异步返回,直接进行某种操作,比如oc中的弹框,popViewController或者是pushViewController操作。

    1. 第二个按钮的触发实现操作如下。
      第二个按钮直接触发的语句为:
    var cookie = window.prompt("getCookie");
    

    直接获取cookie,prompt方法会直接被oc的WKUIDelegate代理中的runJavaScriptTextInputPanelWithPrompt代理方法所捕获到。
    prompt有两个参数,第一个是prompt,第二个defaulttext,分别和代理方法中相对应。
    代理方法实现如下:

    1.  
      #pragma mark - WKUIDelegate delegate method
    2.  
      - (void)webView:(WKWebView *)webView
    3.  
      runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt
    4.  
      defaultText:(NSString *)defaultText
    5.  
      initiatedByFrame:(WKFrameInfo *)frame
    6.  
      completionHandler:(void (^)(NSString * _Nullable))completionHandler {
    7.  
      if (prompt) {
    8.  
      if ([prompt isEqualToString: @"getCookie"]) {
    9.  
      completionHandler(@"eba7392f-f754-4a56-9c22-aedf3ffb79d8");
    10.  
      }
    11.  
      }
    12.  
      }

    这样由js调用oc便实现了。

    结束语

    本文没有使用第三方库的实现,只是调研了原生的类库的使用方式。其实可以研究一下第三方类库wkwebviewjavascriptbridge,这样可以保证前端只写一份代码,可以在iOS和Android上共同使用。

    微信公号搜索:李大头头。(或扫描二维码)找我来玩。

    更多【前端技术群】和【内推职位】 资源等着你。

    还不定期在公众号请大家喝奶茶!

    想与我聊聊或者有什么问题都可以在公众号找到我。

    等你哟~

  • 相关阅读:
    芯片测试
    【转】悬浮的对话框
    imagebutton 设置点击和按压效果
    imagebutton 设置了src属性的图片更换
    侧滑实现
    使用自定义的AlertDialog。
    [转]Dialog
    【转】webview的几个问题
    webview 播放H5视频问题 黑屏 只有声音没有画面
    【转】Android HTML5 Video视频标签自动播放与自动全屏问题解决
  • 原文地址:https://www.cnblogs.com/itlover2013/p/14983407.html
Copyright © 2011-2022 走看看