zoukankan      html  css  js  c++  java
  • 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互调的优雅实现方案》
  • 相关阅读:
    「日常训练」Single-use Stones (CFR476D2D)
    「日常训练」Greedy Arkady (CFR476D2C)
    「Haskell 学习」二 类型和函数(上)
    「学习记录」《数值分析》第二章计算实习题(Python语言)
    「日常训练」Alena And The Heater (CFR466D2D)
    Dubbo 消费者
    Dubbo 暴露服务
    Rpc
    git fail to push some refs....
    Spring Cloud (6)config 客户端配置 与GitHub通信
  • 原文地址:https://www.cnblogs.com/Jacue/p/4961561.html
Copyright © 2011-2022 走看看