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 在我的上一 ...
随机推荐
- RecyclerView常见问题解决方案,RecyclerView嵌套自动滚动,RecyclerView 高度设置wrap_content 无作用等问题
1,ScrollView或者RecyclerView1 嵌套RecyclerView2 进入页面自动跳转到recyclerView2上面页面会自动滚动貌似是RecyclerView 自动获得了焦点两 ...
- [Android Security] DEX文件格式分析
copy from : https://segmentfault.com/a/1190000007652937 0x00 前言 分析 dex 文件格式最好的方式是找个介绍文档,自己再写一个简单的 de ...
- scrapy框架系列 (1) 初识scrapy
Scrapy 框架 Scrapy是用纯Python实现一个为了爬取网站数据.提取结构性数据而编写的应用框架,用途非常广泛. 框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页 ...
- Sublime Text 3中SublimeLinter的使用
关于Sublime Text 2中的SublimeLinter的使用网上多如牛毛,基本上不会遇到什么问题,简单的讲一下关于Sublime Text 3中遇到的问题: 1.通过package cont ...
- Word Embedding与Word2Vec
http://blog.csdn.net/baimafujinji/article/details/77836142 一.数学上的“嵌入”(Embedding) Embed这个词,英文的释义为, fi ...
- Shader开发工具: PVRShaman
1. A PVRShaman (.POD) workspace is provided as an example in the Chapter_10/PVR_LinearFog folder tha ...
- hadoop集群配置SSH免登陆
今天给大家总结一下hadoop集群之间免登陆的步骤 node1 ssh node4 1.在node1中生成密钥 [root@node1 ~]# ssh-keygen -t dsa -P '' -f ~ ...
- C++ 构造与析构的执行顺序
1.代码如下:class A{public: int _Id; A():_Id(0) { printf("A[%d]\n",_Id); } ~A() { printf(" ...
- 纪念google reader
2013年3月14日早上,谷歌在其官方博客宣布,2005年推出的 Google Reader 将在7月1号关闭. google reader的历史 以下搞自维基百科http://zh.wikipedi ...
- oracle expdp/impdp 用法详解
http://hi.baidu.com/hzfsai/item/4a4b3fc4b1cf7e51ad00efbd oracle expdp/impdp 用法详解 Data Pump 反映了整个导出/导 ...