WebViewJavascriptBridge源代码分析
初始化OC | 初始化JS |
[WebViewJavascriptBridge bridgeForWebView:(UIWebView/WebView*)webview handler:(WVJBHandler)handler]
[WebViewJavascriptBridge bridgeForWebView:(UIWebView/WebView*)webview webViewDelegate:(UIWebViewDelegate*)webViewDelegate handler:(WVJBHandler)handler]
|
document.addEventListener('WebViewJavascriptBridgeReady', function onBridgeReady(event) { ... }, false)
bridge.init(function messageHandler(data, response) { ... })
|
OC发送消息to JS | JS发送消息to OC |
[bridge send:(id)data]
[bridge send:(id)data responseCallback:(WVJBResponseCallback)responseCallback]
|
bridge.send("Hi there!")
bridge.send({ Foo:"Bar" })
bridge.send(data, function responseCallback(responseData) { ... })
|
OC注冊事件(先) | JS调用事件(后) |
[bridge registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler]
|
WebViewJavascriptBridge.callHandler("handlerName")
|
OC调用事件(后) | JS注冊事件(先) |
[bridge callHandler:(NSString*)handlerName data:(id)data]
[bridge callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)callback]
|
bridge.registerHandler("handlerName", function(responseData) { ... })
|
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" align="middle" alt="" />
if (responseCallback) {
var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime()
responseCallbacks[callbackId] = responseCallback
message['callbackId'] = callbackId
}
sendMessageQueue.push(message)
messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE
}
会拦截请求内容
{
if (webView !=
_webView) { return
YES; }
NSURL *url = [request
URL];
__strong
WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate =
_webViewDelegate;
if ([_baseisCorrectProcotocolScheme:url]) {
if ([_baseisCorrectHost:url]) {
NSString *messageQueueString = [self_evaluateJavascript:[_basewebViewJavascriptFetchQueyCommand]];
[_base
flushMessageQueue:messageQueueString];
} else {
[_base
logUnkownMessage:url];
}
return
NO;
} else
if (strongDelegate && [strongDelegate
respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) {
return [strongDelegate
webView:webView shouldStartLoadWithRequest:requestnavigationType:navigationType];
} else {
return
YES;
}
return
@"WebViewJavascriptBridge._fetchQueue();";
id messages = [self_deserializeMessageJSON:messageQueueString];
if (![messages
isKindOfClass:[NSArray
class]]) {
NSLog(@"WebViewJavascriptBridge: WARNING: Invalid %@ received: %@", [messagesclass], messages);
return;
}
for (WVJBMessage* messagein messages) {
if (![message
isKindOfClass:[WVJBMessage
class]]) {
NSLog(@"WebViewJavascriptBridge: WARNING: Invalid %@ received: %@", [messageclass], message);
continue;
}
[self
_log:@"RCVD"
json:message];
NSString* responseId = message[@"responseId"];
if (responseId) {
WVJBResponseCallback responseCallback =_responseCallbacks[responseId];
responseCallback(message[@"responseData"]);
[self.responseCallbacksremoveObjectForKey:responseId];
} else {
WVJBResponseCallback responseCallback =NULL;
NSString* callbackId = message[@"callbackId"];
if (callbackId) {
responseCallback = ^(id responseData) {
if (responseData ==
nil) {
responseData = [NSNullnull];
}
WVJBMessage* msg = @{@"responseId":callbackId,
@"responseData":responseData };
[self
_queueMessage:msg];
};
} else {
responseCallback = ^(id ignoreResponseData) {
// Do nothing
};
}
WVJBHandler handler;
if (message[@"handlerName"]) {
handler = self.messageHandlers[message[@"handlerName"]];
} else {
handler = self.messageHandler;
}
if (!handler) {
[NSException
raise:@"WVJBNoHandlerException"
format:@"No handler for message from JS: %@", message];
}
handler(message[@"data"], responseCallback);
}
}
if (self.startupMessageQueue) {
[self.startupMessageQueueaddObject:message];
} else {
[self
_dispatchMessage:message];
}
NSString *messageJSON = [self_serializeMessage:message];
[self
_log:@"SEND"
json:messageJSON];
messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\\"withString:@"\\\\"];
messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\""withString:@"\\\""];
messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\'"withString:@"\\\'"];
messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\n"withString:@"\\n"];
messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\r"withString:@"\\r"];
messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\f"withString:@"\\f"];
messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\u2028"withString:@"\\u2028"];
messageJSON = [messageJSON stringByReplacingOccurrencesOfString:@"\u2029"withString:@"\\u2029"];
NSString* javascriptCommand = [NSStringstringWithFormat:@"WebViewJavascriptBridge._handleMessageFromObjC('%@');",
messageJSON];
if ([[NSThreadcurrentThread]
isMainThread]) {
[self
_evaluateJavascript:javascriptCommand];
} else {
dispatch_sync(dispatch_get_main_queue(), ^{
[self
_evaluateJavascript:javascriptCommand];
});
}
setTimeout(function _timeoutDispatchMessageFromObjC() {
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({ responseId:callbackResponseId, responseData:responseData })
}
}
var handler = WebViewJavascriptBridge._messageHandler
if (message.handlerName) {
handler = messageHandlers[message.handlerName]
}
try {
handler(message.data, responseCallback)
} catch(exception) {
if (typeof console != 'undefined') {
console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception)
}
}
}
})
}
handlerName:nil];
_queueMessage
(void)flushMessageQueue:(NSString *)messageQueueString解析,OC側运行之前注冊的handler并传入data数据
[self
callHandler:handlerName data:dataresponseCallback:nil];
{
[_base
sendData:data responseCallback:responseCallbackhandlerName:handlerName];
handlerName:(NSString*)handlerName中处理
WebViewJavascriptBridge源代码分析的更多相关文章
- android-plugmgr源代码分析
android-plugmgr是一个Android插件加载框架,它最大的特点就是对插件不需要进行任何约束.关于这个类库的介绍见作者博客,市面上也有一些插件加载框架,但是感觉没有这个好.在这篇文章中,我 ...
- Twitter Storm源代码分析之ZooKeeper中的目录结构
徐明明博客:Twitter Storm源代码分析之ZooKeeper中的目录结构 我们知道Twitter Storm的所有的状态信息都是保存在Zookeeper里面,nimbus通过在zookeepe ...
- 转:SDL2源代码分析
1:初始化(SDL_Init()) SDL简介 有关SDL的简介在<最简单的视音频播放示例7:SDL2播放RGB/YUV>以及<最简单的视音频播放示例9:SDL2播放PCM>中 ...
- 转:RTMPDump源代码分析
0: 主要函数调用分析 rtmpdump 是一个用来处理 RTMP 流媒体的开源工具包,支持 rtmp://, rtmpt://, rtmpe://, rtmpte://, and rtmps://. ...
- 转:ffdshow 源代码分析
ffdshow神奇的功能:视频播放时显示运动矢量和QP FFDShow可以称得上是全能的解码.编码器.最初FFDShow只是mpeg视频解码器,不过现在他能做到的远不止于此.它能够解码的视频格式已经远 ...
- UiAutomator源代码分析之UiAutomatorBridge框架
上一篇文章<UIAutomator源代码分析之启动和执行>我们描写叙述了uitautomator从命令行执行到载入測试用例执行測试的整个流程.过程中我们也描写叙述了UiAutomatorB ...
- MyBatis架构设计及源代码分析系列(一):MyBatis架构
如果不太熟悉MyBatis使用的请先参见MyBatis官方文档,这对理解其架构设计和源码分析有很大好处. 一.概述 MyBatis并不是一个完整的ORM框架,其官方首页是这么介绍自己 The MyBa ...
- hostapd源代码分析(三):管理帧的收发和处理
hostapd源代码分析(三):管理帧的收发和处理 原文链接:http://blog.csdn.net/qq_21949217/article/details/46004379 这篇文章我来讲解一下h ...
- hostapd源代码分析(二):hostapd的工作机制
[转]hostapd源代码分析(二):hostapd的工作机制 原文链接:http://blog.csdn.net/qq_21949217/article/details/46004433 在我的上一 ...
随机推荐
- 两种方法获取MyBatis刚刚插入的id
主要就是在xml文件中的写法,其他省略 方法一: <insert id="insert" parameterType="com.xxx.xxxx.pojo.User ...
- mongodb 脚本操作
MO='mongo'$MO << EOFuse testdbdb.dropDatabase()show dbsexit;EOF
- 将Linux默认的OpenJDK替换为Oracle JDK
在使用Logstash安装插件的时候,发生了一个错误,如下: ERROR: Something went wrong when installing logstash-input-jdbc, mess ...
- SVG 使用marker画箭头(一)
一.使用Marker画箭头 1.定义一个箭头的marker引用 <defs> <marker id='markerArrow' markerWidth='13' markerHeig ...
- Java中的Future模式原理自定义实现
摘要:Future模式类似于js中的ajax等,是一个异步获取数据的机制,这里我把自己的一些形象理解通过代码实现了一下.该机制可以形象的理解为:调用获取数据的方法,首先获得一个没有装数据的空箱子(这个 ...
- [转]php socket编程通信
FROM : http://blog.csdn.net/baixiaoshi/article/details/9399083 今天终于测试成功了php中的socket通信,先看原理图 这里可以清晰的看 ...
- idea自动生成serialVersionUID , serialVersionUID的作用
Java的序列化的机制通过判断serialVersionUID来验证版本的一致性.在反序列化的时候与本地的类的serialVersionUID进行比较,一致则可以进行反序列化,不一致则会抛出异常Inv ...
- @Tomcat中的几种log
日志是程序员居家旅行必备,哦不对,是定位问题,修复bug,甚至是验证应用是否正常的必备利器.甚至很多时候,我们做一次部署仅仅是为了加一行log.虽然现在有各种各样的问题诊断工具,但是在定位线上问题时, ...
- iOS开发-View中frame和bounds区别
开发中调整View的时候的经常会遇到frame和bounds,刚开始看的时候不是很清楚,不过看了一下官方文档,frame是确定视图在父视图中的位置,和本身的大小,bounds确定可以确定子视图在当前视 ...
- adb 环境配置 常用命令 总结
配置环境变量 右键我的电脑 -> 属性 -> 高级 -> 环境变量 -> Path 在Path中添加Android SDK安装路径中 adb.exe 的路径,例如[\sdk\p ...