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 在我的上一 ...
随机推荐
- UIWebView加载CSS样式的html
UIWebView加载CSS样式的html 效果 源码 // // ViewController.m // CSS // // Created by YouXianMing on 16/7/19. / ...
- 开源项目MultiChoiceAdapter详解(五)——可扩展的MultiChoiceBaseAdapter
上次写到了开源项目MultiChoiceAdapter详解(四)——MultiChoiceBaseAdapter的使用,其实我们仍旧可以不使用ActionMode的,所以这里就写一个自己扩展的方法. ...
- [Android Pro] 自己动手编译Android源码(超详细)
cp from : https://www.jianshu.com/p/367f0886e62b 在Android Studio代码调试一文中,简单的介绍了代码调试的一些技巧.现在我们来谈谈andro ...
- [转]ThinkPHP的CURD易忽视点小结
转自: http://www.oschina.net/code/snippet_2285640_44437. 1.使用对象的方法插入数据 D用法. $Form = D('Form'); $data[' ...
- [转]php-mobile-detect
转自:http://www.oschina.net/p/php-mobile-detect php-mobile-detect (Mobile_Detect) 是一个 PHP 类,用来通过 User- ...
- javascript中使用new与不使用实例化对象的区别
我们先来看个实例 function Me(name,age,job){ this.name = name; this.age = age; this.job = job; } 请问这以下两种实例化对象 ...
- 奇怪吸引子---AnishchenkoAstakhov
奇怪吸引子是混沌学的重要组成理论,用于演化过程的终极状态,具有如下特征:终极性.稳定性.吸引性.吸引子是一个数学概念,描写运动的收敛类型.它是指这样的一个集合,当时间趋于无穷大时,在任何一个有界集上出 ...
- go语言之进阶篇Ticker的使用
Ticker是一个定时触发的计时器,它会以一个间隔(interval)往channel发送一个事件(当前时间),而channel的接收者可以以固定的时间间隔从channel中读取事件. 1.Ticke ...
- go语言之进阶篇error接口的使用
1.error接口的使用 示例: package main import "fmt" import "errors" func main() { //var e ...
- 读书笔记,《Java 8实战》第五章,使用流
本章我们将会了解到关于Stream API的很多操作,这些操作能够完成很多复杂的查询,比如,比如筛选,切片,映射,查找,匹配和规约, 第一节,筛选和切片 首先我们来看看用谓词来选择流动的元素,主 ...