close
当前位置: 物联网在线 > 技术文库 > ios >

WebViewJavascriptBridge原理解析(5)

具体注入的javascript字符串如下:

WebViewJavascriptBridge._handleMessageFromObjC('{\"callbackId\":\"objc_cb_1\",\"data\":{\"OC调用JS方法\":\"OC调用JS方法的参数\"},\"handlerName\":\"OC调用JS提供的方法\"}');

其实就是通过javascript环境中的Bridge对象的 _handleMessageFromObjC 方法。下面我们去 WebViewJavascriptBridege_JS.js 中看 _handleMessageFromObjC 的处理过程。

//处理从OC返回的消息。 function _dispatchMessageFromObjC(messageJSON) { if (dispatchMessagesWithTimeoutSafety) { setTimeout(_doDispatchMessageFromObjC); } else { _doDispatchMessageFromObjC(); } function _doDispatchMessageFromObjC() { var message = JSON.parse(messageJSON); var messageHandler; var responseCallback; //回调 if (message.responseId) { responseCallback = responseCallbacks[message.responseId]; if (!responseCallback) { return; } responseCallback(message.responseData); delete responseCallbacks[message.responseId]; } else {//主动调用 if (message.callbackId) { var callbackResponseId = message.callbackId; responseCallback = function(responseData) { _doSend({ handlerName: message.handlerName, responseId: callbackResponseId, responseData: responseData }); }; } //获取JS注册的函数 var handler = messageHandlers[message.handlerName]; if (!handler) { console.log("WebViewJavascriptBridge: WARNING: no handler for message from ObjC:", message); } else { //调用JS中的对应函数处理 handler(message.data, responseCallback); } } } }

上面这段代码很容易理解,其实就是如果消息中有callbackId则表示是一个回调。直接调用_doSend方法把信息返回OC。否则就是Web环境主动调用OC的情况。此时把callbackID、handlerName、responseCallback封装进一个message对象中保存起来(其实你会发现和OC环境的bridge处理一样)。然后通过_doSend发消息发送到OC环境。下面我们看看_doSend的具体实现:

//把消息从JS发送到OC,执行具体的发送操作。 function _doSend(message, responseCallback) { if (responseCallback) { var callbackId = 'cb_' + (uniqueId++) + '_' + new Date().getTime(); //存储消息的回调ID responseCallbacks[callbackId] = responseCallback; //把消息对应的回调ID和消息一起发送,以供消息返回以后使用。 message['callbackId'] = callbackId; } //把消息放入消息列表 sendMessageQueue.push(message); //下面这句话会出发JS对OC的调用 //让webview执行跳转操作,从而可以在 //webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler 中拦截到JS发给OC的消息 messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE; }

其中最重要还是最后面的通过改变iframe的 messagingIframe.src 。从而触发webview的代理方法 webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler 从而在OC中处理javascript环境触发过来的回调。具体如下:

if ([_base isWebViewJavascriptBridgeURL:url]) { //第一次注入JS代码 if ([_base isBridgeLoadedURL:url]) { [_base injectJavascriptFile]; //处理WEB发过来的消息 } else if ([_base isQueueMessageURL:url]) { [self WKFlushMessageQueue]; } else { [_base logUnkownMessage:url]; } decisionHandler(WKNavigationActionPolicyCancel); }

这里会走 [self WKFlushMessageQueue]; 方法。然后通过调用 WebViewJavascriptBridge._fetchQueue() 来获取javascript给OC的回调信息。

//获取WEB消息的JSON字符串 - (NSString *)webViewJavascriptFetchQueyCommand { return @"WebViewJavascriptBridge._fetchQueue();"; } ////把消息或者WEB回调从OC发送到OC - (void)WKFlushMessageQueue { NSString *js = [_base webViewJavascriptFetchQueyCommand]; [_webView evaluateJavaScript:js completionHandler:^(NSString* result, NSError* error) { if (error != nil) { NSLog(@"WebViewJavascriptBridge: WARNING: Error when trying to fetch data from WKWebView: %@", error); } //把消息或者WEB回调从OC发送到OC [_base flushMessageQueue:result]; }]; }

获取到javascript给OC的回调消息以后,然后把javascript的bridge返回的信息加工处理成OC环境的bridge能识别的信息。从而找到具体的实现执行。

//把从WEB发送的消息返回。然后在这里处理 - (void)flushMessageQueue:(NSString *)messageQueueString{ if (messageQueueString == nil || messageQueueString.length == 0) { NSLog(@"WebViewJavascriptBridge: WARNING: ObjC got nil while fetching the message queue JSON from webview. This can happen if the WebViewJavascriptBridge JS is not currently present in the webview, e.g if the webview just loaded a new page."); return; } id messages = [self _deserializeMessageJSON:messageQueueString]; for (WVJBMessage* message in messages) { if (![message isKindOfClass:[WVJBMessage class]]) { NSLog(@"WebViewJavascriptBridge: WARNING: Invalid %@ received: %@", [message class], message); continue; } [self _log:@"RCVD" json:message]; NSString* responseId = message[@"responseId"]; if (responseId) { WVJBResponseCallback responseCallback = _responseCallbacks[responseId]; responseCallback(message[@"responseData"]); [self.responseCallbacks removeObjectForKey:responseId]; } else { WVJBResponseCallback responseCallback = NULL; NSString* callbackId = message[@"callbackId"]; if (callbackId) { responseCallback = ^(id responseData) { if (responseData == nil) { responseData = [NSNull null]; } WVJBMessage* msg = @{ @"responseId":callbackId, @"responseData":responseData }; [self _queueMessage:msg]; }; } else { responseCallback = ^(id ignoreResponseData) { // Do nothing }; } WVJBHandler handler = self.messageHandlers[message[@"handlerName"]]; if (!handler) { NSLog(@"WVJBNoHandlerException, No handler for message from JS: %@", message); continue; } handler(message[@"data"], responseCallback); } } }
(责任编辑:ioter)

用户喜欢...

我们和毫米波雷达来一次“亲密接触”,了解一下它的概念和工作原理

无论是激光雷达还是摄像头、超声波传感器,都容易受恶劣天气环境影响导致性能降低甚至失效,因而都存在致命缺陷!但毫米波雷达凭借其可穿透尘雾、雨雪、不受恶劣天气影响的绝对优势,...


对数放大器的基本原理及其处理宽动态范围信号的方法

使用高动态范围信号对设计人员来说是一个主要问题。 如何将幅度变化超过100分贝(dB)的信号应用于线性放大器或模数转换器(ADC),典型动态范围为60 dB至100 dB? 像这样的信号发生在回波...


使用 ToF 传感器进行距离测量和手势识别的基本原理

很多应用需要在不接触实际物体的情况下,感测物体的存在或距离。这种接近感应需求催生了众多竞争性解决方案,包括光学飞行时间 (ToF) 传感器。虽然这些传感器非常精确,但其成本一直非...


电流测量的基本原理:第 1 部分 - 电流检测电阻器

编者按:本系列文章包含两个部分,将介绍电流检测中容易忽视的细节。本文为第 1 部分,将讨论电流检测电阻的一般设置、选择和实现。第 2 部分将讨论相关电路,例如关键的模拟前端 (AF...


什么是锁相环(PLL)?锁相环的工作原理是什么?锁相环电路对硬件电路连接有什么要求?

锁相环是一种反馈电路,其作用是使得电路上的时钟和某一外部时钟的相位同步。PLL通过比较外部信号的相位和由压控晶振(VCXO)的相位来实现同步的,在比较的过程中,锁相环电路会不断根...


IBM解析2018年最流行的五项IoT趋势

2017年,物联网技术(loT)为传统行业带来了变革的风声和兴奋的议论。这是一场实质性的转变。我们已经能够看到,几乎所有的行业都在投资物联网,而且其中的佼佼者已经开始迅速采取行...


神经网络从原理到实现

1.简单介绍 在机器学习和认知科学领域,人工神经网络(artificial neural network,缩写ANN),简称神经网络(neural network,缩写NN)或类神经网络,是一种模仿生物神经网络(动物的中枢神经系统,...


自动扫地机器人好用吗?智能特性全面解析

生活在如今这样一个节奏快、工作压力大的时代,我们的压力也是越发的大了,但是人类的智慧是强大的,智能家居...


unity静态批处理原理理解

1、静态批处理的时间点 1)在游戏导出的时候,在player setting中勾选static batching,这样在导出包的时候就进行批处理,导出来的包就会比较大 2 ) 在游戏场景中勾选场景物体的static选项,在加...


统计模式识别的原理与方法

1 统计模式识别的原理与方法简介 1.1 模式识别 什么是模式和模式识别? 广义地说,存在于时间和空间中可观察的事物,如果可以区别它们是否相同或相似,都可以称之为模式;狭义地说,模...