WebViewJavascriptBridge源码解读
2017-05-19 11:28
465 查看
WebViewJavascriptBridge是一个连接JavaScript和iOS Native交互的开源框架,github地址, 使用它可以在UIWebview中响应事件并执行Native方法,也可以使用Native方法调用javascript方法, 正如其名,它好像已做桥梁连接了两端.
首先看看如何使用它, 通过cocopods或直接拖进工程后引入头文件 WebViewJavascriptBridge.h, 它提供的方法比较简单和使用.
Native端
首先初始化方法:
webView: 我们Native中初始化的
handler: 回调块,返回javascript返回的数据
webViewDelegate: 我们的webView的代理对象,要处理webView事件的对象
bundle: WebViewJavascriptBridge.js.text 文件所在的bundle, 在webView回调中会找到它
然后我们可以通过
方法给javascript发送数据, javascript在执行的init的时候会收到这些数据, 可以是webView需要展示的数据. message可以自定义, 这些数据在javascript中需要自己解析使用,responseCallback是收到数据后的回调方法.
最后我们通过
注册一些方法, handlerName为约定好的字符串, 这些注册的方法是由javascript调用的, Native在 handler中收到响应并处理
我们也可以向javascript发送消息
至此 Navtive配置好了, javascript端需要做的是添加一个javascript方法
改方法会初始化一个WebViewJavascriptBridge的对象, 而且只初始化一次,然后再javascript中就可以使用这个对象的方法发送和接受消息了
那么 WebViewJavascriptBridge 内部是如何实现的呢?
首先 它的源文件有两部分组成,WebViewJavascriptBridge .h和.m 两个iOS类, WebViewJavascriptBridge.js.txt javascript类.
在 WebViewJavascriptBridge.m 中 有3个集合对象
当初始化bridge的时候,bridge会将webView的代理注册给自己, 自己实现了UIWebview的几个代理方法,用于处理消息.
当webView向bridge注册消息的时候, bridge会以消息名为key, 回调块为value存入_messageHandlers中.
当webView向javascript发送消息的时候 会调用 send: 或 callHandler: 等方法, 其内部会构建一个消息字典, 字典中存储 发送的data, 回调块, 消息ID 和 方法名字, 类似这样的结构: { ‘data’ : data, ‘callbackId’ : objc_cb_1, ‘handlerName’ : handlerName } 其中ID为自增ID objc_cb_1,2,3.. 而且用_responseCallbacks保存了一份 ID和回调块. 构造的消息字典会加入_startupMessageQueue中等待分发消息到javascript.
这些消息是如何分发的呢?
bridge是在UIWebview的代理方法 webViewDidFinishLoad 当webView加载完后会调用的方法中, 遍历_startupMessageQueue, 这里面存放了带分发的消息字典, 遍历每一个消息字典调用- (void)_dispatchMessage:(WVJBMessage*)message 分发消息, 里面执行了一个javascript方法 WebViewJavascriptBridge._dispatchMessageFromObjC(data) 这方法在 WebViewJavascriptBridge.js.txt 中定义, 里面也实现了和 WebViewJavascriptBridge.m 一样的逻辑,进而调用javascript方法, 达到消息传递.
那么javascript如何将消息传递给Native的呢?
当然也是通过UIWebview的代理方法传递啦.
这个方法会在加载webView之前调用, 询问是否要加载,它可以捕获到uiwebview的请求.故, bridge在WebViewJavascriptBridge.js.txt 中收到javascript的方法调用后设置了一下HTML的IFrame, 算是发出了一个请求: messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + ‘://’ + QUEUE_HAS_MESSAGE 这样就会触发UIWebview shouldStartLoadWithRequest 方法, 在该方法中, bridge按照自定义的格式解析参数 并从_responseCallbacks 中取出保存过的回调块进行回调.
这样就完成了javascript和Native之间的通信.
首先看看如何使用它, 通过cocopods或直接拖进工程后引入头文件 WebViewJavascriptBridge.h, 它提供的方法比较简单和使用.
Native端
首先初始化方法:
- (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView handler:(WVJBHandler)handler; - (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)handler; - (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)handler resourceBundle:(NSBundle*)bundle;
webView: 我们Native中初始化的
handler: 回调块,返回javascript返回的数据
webViewDelegate: 我们的webView的代理对象,要处理webView事件的对象
bundle: WebViewJavascriptBridge.js.text 文件所在的bundle, 在webView回调中会找到它
然后我们可以通过
- (void)send:(id)message; - (void)send:(id)message responseCallback:(WVJBResponseCallback)responseCallback
方法给javascript发送数据, javascript在执行的init的时候会收到这些数据, 可以是webView需要展示的数据. message可以自定义, 这些数据在javascript中需要自己解析使用,responseCallback是收到数据后的回调方法.
最后我们通过
- (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler;
注册一些方法, handlerName为约定好的字符串, 这些注册的方法是由javascript调用的, Native在 handler中收到响应并处理
我们也可以向javascript发送消息
- (void)callHandler:(NSString*)handlerName; - (void)callHandler:(NSString*)handlerName data:(id)data; - (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback;
至此 Navtive配置好了, javascript端需要做的是添加一个javascript方法
function connectWebViewJavascriptBridge(callback) { if (window.WebViewJavascriptBridge) { callback(WebViewJavascriptBridge) } else { document.addEventListener('WebViewJavascriptBridgeReady', function() { callback(WebViewJavascriptBridge) }, false) } }
改方法会初始化一个WebViewJavascriptBridge的对象, 而且只初始化一次,然后再javascript中就可以使用这个对象的方法发送和接受消息了
connectWebViewJavascriptBridge(function(bridge) { /* Init your app here */ // 初始化bridge bridge.init(function(message, responseCallback) { alert('Received message: ' + message) if (responseCallback) { responseCallback("Right back atcha") } }) // 发送消息到Native bridge.send('Hello from the javascript') bridge.send('Please respond to this', function responseCallback(responseData) { console.log("Javascript got its response", responseData) }) }) // 注册消息, 接受Native发来的消息 bridge.registerHandler('setFontEvent', function(data, responseCallback) { setFontSize(data) })
那么 WebViewJavascriptBridge 内部是如何实现的呢?
首先 它的源文件有两部分组成,WebViewJavascriptBridge .h和.m 两个iOS类, WebViewJavascriptBridge.js.txt javascript类.
在 WebViewJavascriptBridge.m 中 有3个集合对象
// 存放Native发来的消息 NSMutableArray* _startupMessageQueue; // 存放Native实现的回调块 NSMutableDictionary* _responseCallbacks; // 存放Native和javascript约定的消息名字 NSMutableDictionary* _messageHandlers;
当初始化bridge的时候,bridge会将webView的代理注册给自己, 自己实现了UIWebview的几个代理方法,用于处理消息.
当webView向bridge注册消息的时候, bridge会以消息名为key, 回调块为value存入_messageHandlers中.
当webView向javascript发送消息的时候 会调用 send: 或 callHandler: 等方法, 其内部会构建一个消息字典, 字典中存储 发送的data, 回调块, 消息ID 和 方法名字, 类似这样的结构: { ‘data’ : data, ‘callbackId’ : objc_cb_1, ‘handlerName’ : handlerName } 其中ID为自增ID objc_cb_1,2,3.. 而且用_responseCallbacks保存了一份 ID和回调块. 构造的消息字典会加入_startupMessageQueue中等待分发消息到javascript.
这些消息是如何分发的呢?
bridge是在UIWebview的代理方法 webViewDidFinishLoad 当webView加载完后会调用的方法中, 遍历_startupMessageQueue, 这里面存放了带分发的消息字典, 遍历每一个消息字典调用- (void)_dispatchMessage:(WVJBMessage*)message 分发消息, 里面执行了一个javascript方法 WebViewJavascriptBridge._dispatchMessageFromObjC(data) 这方法在 WebViewJavascriptBridge.js.txt 中定义, 里面也实现了和 WebViewJavascriptBridge.m 一样的逻辑,进而调用javascript方法, 达到消息传递.
那么javascript如何将消息传递给Native的呢?
当然也是通过UIWebview的代理方法传递啦.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
这个方法会在加载webView之前调用, 询问是否要加载,它可以捕获到uiwebview的请求.故, bridge在WebViewJavascriptBridge.js.txt 中收到javascript的方法调用后设置了一下HTML的IFrame, 算是发出了一个请求: messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + ‘://’ + QUEUE_HAS_MESSAGE 这样就会触发UIWebview shouldStartLoadWithRequest 方法, 在该方法中, bridge按照自定义的格式解析参数 并从_responseCallbacks 中取出保存过的回调块进行回调.
这样就完成了javascript和Native之间的通信.
相关文章推荐
- WebViewJavascriptBridge源码解读
- WebViewJavascriptBridge源码探究--看OC和JS交互过程(介绍了WebViewJavascriptBridge的实现过程)
- iOS WebViewJavascriptBridge源码解析
- WebViewJavascriptBridge源码分析
- WebViewJavaScriptBridge源码解析(一)
- WebViewJavascriptBridge源码探究--看OC和JS交互过程
- iOS WebView JavascriptBridge 源码解析
- iOS源码解析—WebViewJavascriptBridge
- WebViewJavascriptBridge源码探究--看OC和JS交互过程
- WebViewJavascriptBridge-优秀开源代码解读:JS与iOS Native Code互调
- WebViewJavascriptBridge工程结构和源码解析
- WebViewJavascriptBridge源码解析 -1
- WebViewJavaScriptBridge源码解析
- WebViewJavascriptBridge-->实现JS和iOS之间的互调
- Android 利用WebViewJavascriptBridge 实现js和java的交互(一)
- OC-JS交互(WebViewJavascriptBridge使用说明)
- WebViewJavascriptBridge使用说明(IOS)
- 通过WebViewJavascriptBridge实现OC与JS交互
- IOS-WebViewJavascriptBridge使用说明
- iPhone 和 iPad的ios 开发中 利用 WebViewJavascriptBridge组件,通过 UIWebView 对Html进行双向通讯