理解WebViewJavaScriptBridge原理

前提条件都是需要bridge在OC实例化,然后二者的互调才可以进行下去

_bridge = [WebViewJavascriptBridge bridgeForWebView:webView];

实例化的原理是:JSBridge里面有UIWebview和JSBridgeBase的实例,然后分别成为二者的代理,负责协调双方的工作

第一部分:js调用OC方法:

由OC注册,JS主动触发(调用callhandler方法)

1.执行前提条件

2.OC在注册(registerHandler)的时候,OC会注册一个回调函数

[_bridge registerHandler:@"testObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback)

,该回调函数包括一个注册事件和一个回调方法,JSB中的base实例会把该注册事件放进到base的一个消息池子(负责接受多个OC注册事件)中,方便后续处理

3.网页加载出来后整个oc的执行流程

相当于JS的注册绑定方法--->当UIWebview把该网页加载出来的时候,在该html文件中会通过JS的iframe元素执行JS和OC端的绑定。

该方法是由于webview的delegate设置为了JSB,所以会在JSB中触发其代理方法:shouldStartLoadWithRequest,然后在该方法中进行如下操作:

根据url(此时的url是由上述的iframe元素带进来的,类似:wvjbscheme://BRIDGE_LOADED ) ,来决定此时是走registerHandler 还是 callHandler方法,此时是register方法,那么则执行JSBridgeBase的injectJavascriptFile方法(正如函数名一样,此时执行在工程里面放置的JS文件(在我们的工程里面由于要兼容JSBridge的历史版本,所以这里是在webViewDidFinishLoad里面直接调用injectJavascriptFile方法)),这个文件的主要作用就是向OC发消息来定义一些常量,注册一些实例,定义一些回调方法,方便在OC的逻辑中进行处理和跟踪,文件执行完毕后,接下来就会查找在base中时候有OC要发送给JS的回调信息,没有则执行结束(这里显然没有)

4.oc和js相互绑定过后,此时由JS触发OC函数

点击JS上的button会触发callHandler,会触发代理shouldStartLoadWithRequest:

此时由于经由上述的JS文件执行的时候会执行一个叫做window.WebViewJavascriptBridge的注册

window.WebViewJavascriptBridge = {
registerHandler: registerHandler,
callHandler: callHandler,
disableJavscriptAlertBoxSafetyTimeout: disableJavscriptAlertBoxSafetyTimeout,
_fetchQueue: _fetchQueue,
_handleMessageFromObjC: _handleMessageFromObjC
};

由于js主动触发了callHandler,url所以变成了

wvjbscheme://WVJB_QUEUE_MESSAGE ,所以此时会走一个执行js函数的方法(猜测是通过上述js文件的作用从而能够解析出JS传递过来的信息)来从网页上获得网页的传递过来的信息!

{
"callbackId" : "cb_2_1468844907930",
"handlerName" : "testObjcCallback",
"data" : {
"foo" : "bar"
}
}

然后进入base的flushMessageQueue:函数,在里面通过解析该dict,从而获得注册事件名handlerName,然后获得该事件的回调,并调用那个事件的回调block

handler(message[@"data"], responseCallback);

至此,整个JS回调OC过程完成,达到了JS给OC发送数据的目的,同时如果OC想要给JS发送消息,只需把信息放进responseCallback就会回调给JS(方法就是第二部分的内容),以达到互相通信的目的



第二部分:OC调用js方法:

由js注册,OC主动触发(调用callhandler方法)

1.执行前提条件

2.网页加载出来后整个oc的执行流程

相当于JS的注册方法--->当UIWebview把该网页加载出来的时候,在该html文件中会通过JS的iframe元素执行JS和OC端的绑定。

该方法的由于webview的delegate设置为了JSb,所以会在JSB中触发其代理方法:shouldStartLoadWithRequest,然后在该方法中进行如下操作:

根据url(此时的url是由上述的iframe元素带进来的,类似:wvjbscheme://BRIDGE_LOADED ) ,来决定此时是走registerHandler 还是 callHandler方法,此时是register方法,那么则执行JSBridgeBase的injectJavascriptFile方法(正如函数名一样,此时执行在工程里面放置的JS文件),这个文件的主要作用就是向OC发消息来定义一些常量,注册一些实例,定义一些回调方法,方便在OC的逻辑中进行处理和跟踪,

其中会执行一个叫做window.WebViewJavascriptBridge的注册

window.WebViewJavascriptBridge = {
registerHandler: registerHandler,
callHandler: callHandler,
disableJavscriptAlertBoxSafetyTimeout: disableJavscriptAlertBoxSafetyTimeout,
_fetchQueue: _fetchQueue,
_handleMessageFromObjC: _handleMessageFromObjC
};

由于js函数中一进来便主动触发了registerHandler,所以url变成了

wvjbscheme://WVJB_QUEUE_MESSAGE

文件执行完毕后,会在JSB中执行

else if ([_base isQueueMessageURL:url]) {
NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]];
[_base flushMessageQueue:messageQueueString];
}

恰好此时url 满足情况,则进入消息分发流程,但是由于此时messageQueueString什么也没有,所以直接跳出

3.OC和js相互绑定过后,此时由OC函数触发JS

点击OC的button,触发OC函数

[_bridge callHandler:@"testJavascriptHandler" data:@{@"name": @"wayne"} responseCallback:^(id responseData)

调用Base的

- (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName

使用dictionary进行消息拼接,形如:

{
callbackId = "objc_cb_1";//定义OC的回调id
data = {
name = wayne;
};//OC传递给JS的数据
handlerName = testJavascriptHandler;//为了区分是哪一个注册事件,以便后续的消息分发
}

封装完成过后,会调用[self _dispatchMessage:message]来进行消息分发,消息分发是在主线程里面执行的,消息的内容经过再次封装过后形似:

WebViewJavascriptBridge._handleMessageFromObjC('{\"callbackId\":\"objc_cb_1\",\"data\":{\"name\":\"wayne\"},\"handlerName\":\"testJavascriptHandler\"}');

WebViewJavascriptBridge._handleMessageFromObjC-->查看JS文件可知,这个文件是给JS使用的,会执行_handleMessageFromObjC的方法把消息分发给JS中的registerHandler中的方法体,OC回调过程结束!!

4.JS传递数据给OC

但是此时在执行JS中的代码的时候发现有回调block,则会执行改block

然后会再次执行UIWebview的代理方法:shouldStartLoadWithRequest函数,此时url已经是

wvjbscheme://WVJB_QUEUE_MESSAGE

文件执行完毕后,会在JSB中执行

else if ([_base isQueueMessageURL:url]) {
NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]];
[_base flushMessageQueue:messageQueueString];
}

messageQueueString由第一部分知识可知:是JS传递过来的数据:

[{
"handlerName":"testJavascriptHandler",
"responseId":"objc_cb_1",
"responseData":
{"Javascript Says":"Right back atcha!==>test"}
}]

执行flushMessageQueue函数:并在里面执行block函数体,获得JS传递过来的数据

至此,互相传递数据过程完毕!

WebViewJavaScriptBridge的原理解析的更多相关文章

  1. [iOS 开发] WebViewJavascriptBridge 从原理到实战 · Shannon's Blog

    前言:iOS 开发中,h5 和原生实现通信有多种方式, JSBridge 就是最常用的一种,各 JSBridge 类库的实现原理大同小异,这篇文章主要是针对当前使用最为广泛的 WebViewJavas ...

  2. [原][Docker]特性与原理解析

    Docker特性与原理解析 文章假设你已经熟悉了Docker的基本命令和基本知识 首先看看Docker提供了哪些特性: 交互式Shell:Docker可以分配一个虚拟终端并关联到任何容器的标准输入上, ...

  3. 【算法】(查找你附近的人) GeoHash核心原理解析及代码实现

    本文地址 原文地址 分享提纲: 0. 引子 1. 感性认识GeoHash 2. GeoHash算法的步骤 3. GeoHash Base32编码长度与精度 4. GeoHash算法 5. 使用注意点( ...

  4. Web APi之过滤器执行过程原理解析【二】(十一)

    前言 上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要.这一节我们简单将讲述在Action方法上.控制器上.全局上以及授 ...

  5. Web APi之过滤器创建过程原理解析【一】(十)

    前言 Web API的简单流程就是从请求到执行到Action并最终作出响应,但是在这个过程有一把[筛子],那就是过滤器Filter,在从请求到Action这整个流程中使用Filter来进行相应的处理从 ...

  6. GeoHash原理解析

    GeoHash 核心原理解析       引子 一提到索引,大家脑子里马上浮现出B树索引,因为大量的数据库(如MySQL.oracle.PostgreSQL等)都在使用B树.B树索引本质上是对索引字段 ...

  7. alibaba-dexposed 原理解析

    alibaba-dexposed 原理解析 使用参考地址: http://blog.csdn.net/qxs965266509/article/details/49821413 原理参考地址: htt ...

  8. 支付宝Andfix 原理解析

    支付宝Andfix 原理解析 使用参考地址: http://blog.csdn.net/qxs965266509/article/details/49802429 原理参考地址: http://blo ...

  9. JavaScript 模板引擎实现原理解析

    1.入门实例 首先我们来看一个简单模板: <script type="template" id="template"> <h2> < ...

随机推荐

  1. QPS,TPS,吞吐量,响应时间详解及关系

    并发数 并发数是指系统同时能处理的请求数量,这个也是反应了系统的负载能力 吞吐量吞吐量是指单位时间内系统能处理的请求数量,体现系统处理请求的能力,这是目前最常用的性能测试指标 响应时间RT(Respo ...

  2. Ubuntu16.04双网卡绑定

    服务器经常有多个网卡,为了保证网络冗余性,一个网卡出现故障时,不导致网络服务中断,可以懂多网卡网卡绑定来解决此问题. 环境: 系统:Ubuntu16.04 网卡:em1 em2 ip:192.168. ...

  3. Luogu P4901 排队 fib数列+树状数组+倍增

    这题让我升华..还好只重构了一遍 首先我们发现:$n$较小时,整个队伍的形态 跟 $n$ 比较大时的局部是一样的 所以我们预处理出这个队伍的形态,和每一行每个位置的质因子个数的前缀和,$O(nlogn ...

  4. 注意ie6的盒模型

    浏览器版本多了,也是一个累,特别是ie家族的. 网上搜罗了一大堆,发现说的和我看到的不一样啊,结果才发现原来是对方表述有问题,省略了几个字就产生了歧义了. 按照网上说的ie6对盒模型解释不符合W3C标 ...

  5. Spring学习(六)整合web开发

    https://www.cnblogs.com/Leo_wl/p/4459274.html 1.加载Spring核心配置文件 //1.加载Spring配置文件,根据创建对对象 ApplicationC ...

  6. java里如何实现对数组中的元素反转[4, 1, 8, 7, 3, 8, 2]变成 [2, 8, 3, 7, 8, 1, 4]

    不多说,直接上干货! 给定一个数组,对其进行反转. {3,1,6,5,8,2} --> {2,8,5,6,1,3}; 其实就是头尾元素的位置置换. package zhouls.bigdata. ...

  7. Unity在Project视图里面显示文件的拓展名

    Unity在Project视图里面显示文件的拓展名 功能脚本如下: using System.IO; using System.Reflection; using UnityEngine; using ...

  8. Shell笔试题2

    1. 从a.log文件中提取包含"WARNING"或"FATAL",同时不包含"IGNOR"的行,然后提取以":"分割的 ...

  9. 关于SQL Server数据库中的标识列

    一.标识列的定义以及特点 SQL Server中的标识列又称标识符列,习惯上又叫自增列. 该种列具有以下三种特点: 1.列的数据类型为不带小数的数值类型 2.在进行插入(Insert)操作时,该列的值 ...

  10. i++ ++i i=i+1 和i+=1

    这几个运算符的差别总是过一段时间就爱搞混,每次需要百度,还是自己记录一下方便查阅. int i=0; System.out.println(i++); 输出:0 int i=0; System.out ...