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 在我的上一 ...
随机推荐
- 【转】从源码来分析ListView
原文:http://yanmingming.sinaapp.com/?p=1251 原文其实不叫这个名字,本文对于原文有一定的修改,觉得这个名字比较适合本篇. 一.ListView 的工作原理 Ada ...
- information_schema系列七
information_schema系列七 这个系列的文章主要是为了能够让自己了解MySQL5.7的一些系统表,统一做一下备注和使用,也希望分享出来让大家能够有一点点的受益. 第七篇主要看一下一下 ...
- C# 异步编程Task整理(二)异常捕捉
一.在任务并行库中,如果对任务运行Wait.WaitAny.WaitAll等方法,或者求Result属性,都能捕获到AggregateException异常. 可以将AggregateExceptio ...
- 【Java并发】JUC—ReentrantReadWriteLock有坑,小心读锁!
好长一段时间前,某些场景需要JUC的读写锁,但在某个时刻内读写线程都报超时预警(长时间无响应),看起来像是锁竞争过程中出现死锁(我猜).经过排查项目并没有能造成死锁的可疑之处,因为业务代码并不复杂(仅 ...
- 虚拟机内存复用技术的比较(XEN系统)
技术途径 业界就该问题定义为虚拟机内存复用(复用干嘛? 当然是为了跑更多的虚拟机呀!) :memory overcommit.围绕次问题主要有4种技术手段,下面简要介绍和分析: 1 气泡驱动(ball ...
- 如何打开google,facebok等网站
用记事本打开 C:\WINDOWS\System32\drivers\etc\hosts 文件,粘贴如下蓝色内容到文件里,然后输入 例如 https://www.google.com https: ...
- 《UNIX环境高级编程》笔记--环境变量
ISO C定义了一个函数getenv,可以用其取环境变量值. #include <stdlib.h> char* getenv(const char* name); //返回与name关联 ...
- 第二章 TypeScript 开发环境搭建
Mac OS X 下 TypeScript 开发环境搭建 一.集成开发环境 WebStrom VSCode 二.安装 TypeScript Homebrew(macOS 缺失的软件包管理器) ruby ...
- [leetcode]Combinations @ Python
原题地址:https://oj.leetcode.com/problems/combinations/ 题意:组合求解问题. 解题思路:这种求组合的问题,需要使用dfs来解决. 代码: class S ...
- Hadoop视频教程汇总
一 慕课网 1.Hadoop大数据平台架构与实践--基础篇(已学习) 链接:https://www.imooc.com/learn/391 2.Hadoop进阶(已学习) 链接:https://www ...