• JS与OC交互文档(Web端)


     1、iOS系统API交互方式

     1.1、Objective-C调用Javascript方法

       前提

      UIWebView已经完全加载完成包含需要调用的页面(注:在UIWebViewDelegate托管中通过监视- (void)webViewDidFinishLoad:(UIWebView *)webView调用来确定页面是否加载完成)。

          方法

      假设某视图对象的子视图属性self.webview加载的页面包含如下Javascript函数:

      function getString(){ return “Hello javascript!”;}

       并且该函数在该页面上可被正常调用,则可以通过形如下面的Objectvie-C方法调用此函数:

      NSString *str = [self.webview stringByEvaluatingJavaScriptFromString:@“getString()"];

       该函数调用实际模拟了页面上的一次Javascript函数调用,因此在该函数内部任何有效的Javascript代码都可被执行!该Objective-C代码返回值为被调用的Javascript代码的返回值,在上例中,str的值将被赋为@”Hello javascript!”。

       被调用的函数可以带有字符串或数值型的参数。若调用的Javascript函数名称带有参数,需保证传进去的参数的格式正确性,特别是字符串参数的引号很容易被忽略。

    1.2、客户端响应页面Javascript代码

      前提:

           需要实现UIWebViewDelegate的- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType托管函数(以下简称跳转监视函数)并将实现了该托管函数的对象设置为UIWebView的delegate。

          方法

           UIWebView的当前页面将要被Javascript代码通过以下方式转向的时候,会调用上述跳转监视函数:

           window.location.href=”http://www.strongsoft.net”;

      此时实现了该托管协议的对象的跳转监视函数会被调用,通过如下代码监视浏览器跳转的地址:

           NSString *url = [[request URL] absoluteString];

      若该托管函数返回值为NO,则页面UIWebView的页面跳转将被否决。利用这一思路,监视页面上的特定格式的跳转地址加以拦截,并执行相应的本地代码,即可实现Javascript与Objective-C代码的交互。

           例如,规定拦截URL地址前缀为”objc:”的所有地址,并且用if…else…语句判定本地需要执行的代码,比如执行doFunc1函数,那么可通过如下Javascript函数进行:

           window.location.href=”objc:doFunc1”;

           此方式实现JS向客户端传递的消息存在于href的字符串中,客户端通过解析字符串提取所需信息。

      

    2、引入第三方库WebViewJavascriptBridge进行交互

      WebViewJavascriptBridge优雅地实现了在使用 UIWebView 时 JS 与 iOS 的 OC 之间的互调,支持消息发送、接收、消息处理器的注册与调用以及设置消息处理的回调。 就像项目的名称一样,它是连接UIWebView和Javascript的bridge。在加入这个项目之后,他们之间的交互处理方式变得很友好。

      一起来看看它的实现吧,它总共就包含了三个文件:

      1 WebViewJavascriptBridge.h  

      2 WebViewJavascriptBridge.m  

      3 WebViewJavascriptBridge.js.txt  

      WebViewJavascriptBridge.js.txt 主要用于衔接 UIWebView 中的 web page ,而 WebViewJavascriptBridge.h/m 则主要用于与 OC 的 native code 打交道。他们作为一个整体,其实起到了一个“桥梁”的作用,这三个文件封装了他们具体的交互处理方式,只开放出一些对外的涉及到业务处理的API,因此你在需要UIWebView与Native code交互的时候,引入该库,则无需考虑太多的交互上的问题。

      出于表达上的需要,对于UIWebView相关的我就称之为Web端,而objc那端的处理代码称之为Native端。

      Web端以及Native端完全是对等的两端,实现也是对等的。一段是消息的发送端,另一段就是接收端。这里为引起混淆,需要解释一下我这里使用的“响应”、“回调”在这个上下文中的定义:

      (1)   响应:接收端给予发送端的应答

      (2)   回调:发送端收到接收端的应答之后在接收端调用的处理逻辑

    下面罗列一下它可以实现的功能(Web端):

    • Web端在初始化时支持设置消息的默认处理器(这里的消息指的是从Native端接收到的消息)
    •  从Web端向Native端发送消息,并支持对于Native端响应后的回调处理的定义
    •  Web端调用Native定义的处理器,并支持Native端响应后的回调处理定义
    •  Web端注册处理器(供Native端调用),并支持给Native端响应处理逻辑的定义

    //给WebViewJavascriptBridgeReady事件注册一个Listener

    <span style="white-space:pre">  </span>

    document.addEventListener('WebViewJavascriptBridgeReady', onBridgeReady, false)

    //事件的响应处理

    <span style="white-space:pre">  </span>

    function onBridgeReady(event) {  

         var bridge = event.bridge

    //初始化操作,并定义默认的消息处理逻辑

    <span style="white-space:pre">  </span>

    bridge.init(function(message) {  

                log('JS got a message', message)  

           })

    //注册一个名为testJavascriptHandler的处理器,并定义用于响应的处理逻辑(该处理器可在native端调用名为testJavascriptHandler的处理器后,进行响应操作) 

    <span style="white-space:pre">  </span>

     bridge.registerHandler('testJavascriptHandler', function(data, response) {  

                log('JS handler testJavascriptHandler was called', data)  

                response.respondWith({ 'Javascript Says':'Right back atcha!'  })  

          })

    //创建一个发送消息给native端的按钮

    <span style="white-space:pre">  </span>  

            var button = document.getElementById('buttons').appendChild(document.createElement('button'))  

            button.innerHTML = 'Send message to ObjC'  

            button.ontouchstart = function(e) {  

                 e.preventDefault()  

                  <span style="white-space:pre">      </span>//发送消息  

                  bridge.send('Hello from JS button')  

            }  

         document.body.appendChild(document.createElement('br'))  

    //创建一个用于调用native端处理器的按钮

     <span style="white-space:pre">  </span>  

            var callbackButton = document.getElementById('buttons').appendChild(document.createElement('button'))  

            callbackButton.innerHTML = 'Fire testObjcCallback'  

            callbackButton.ontouchstart = function(e) {  

                e.preventDefault()  

                log("Calling handler testObjcCallback”)

      

                //调用名为testObjcCallback的native端处理器,并传递参数,同时设置回调处理逻辑(与上面对应,客户端也需register一个同样名称的处理器来进行相应响应)  

                bridge.callHandler('testObjcCallback', {'foo': 'bar'}, function(response) {  

                    log('Got response from testObjcCallback', response)  

                })  

            }  

        }  

    3、iOS 8以上系统的交互

      iOS 8之后引入了WKWebView,客户端有系统API来处理Web端发送过来的消息,Web端需要做的也精简不少,代码如下:

      window.webkit.messageHandlers.testObjcCallbackIniOS8.postMessage({

        "infomation": "someData","

      });

    其中,testObjcCallbackIniOS8是Web端调用Native端的处理器的名称,Native端可在相应方法中,进行判断并处理。

    五、参考资料

    1. http://zh.5long.me/2015/ios-objective-c-javascript-bridge/    《iOS开发之Objective-C(Swift)与JavaScript交互·WebViewJavascriptBridge使用篇》
    2. http://www.cnblogs.com/YouXianMing/p/3738317.html   《使用WebViewJavascriptBridge与UIWebView交互》
    3. http://blog.csdn.net/yanghua_kobe/article/details/8209751   《优秀开源代码解读之JS与iOS Native Code互调的优雅实现方案》
  • 相关阅读:
    PHP引用传值
    PHP快速排序
    PHP冒泡排序法
    Jquery EasyUI datagrid后台数据表格生成及分页详解
    polymer 测试
    imooc movie
    test markdown
    MEAN 27
    MEAN 26
    nodejs 负载均衡
  • 原文地址:https://www.cnblogs.com/Jacue/p/4961561.html
Copyright © 2020-2023  润新知