phonegap源码分析(三)------ IOS
来源:互联网 发布:网络平台建设 编辑:程序博客网 时间:2024/05/16 07:33
几个月前看过phonegap在Android和WP上的实现源码,当时苦于没mac环境,直到现在才抽出时间学习了一下phonegap是如何让JS与native串联起来的。
phonegap在IOS上和在WP很类似,由于IOS App内置的WebBrowser提供了比较好的与JS的互通机制,所以整个代码读起来比较轻松,架构图如下所示:
其中有这么几个点值得强调一下:
- Phonegap IOS的项目结构及初始化过程
- JS调用Native
- Native向JS返回结果
1)Phonegap IOS的项目结构及初始化过程
Phonegap IOS的项目结构非常简单,其实就是一个标准的单View的IOS App。只不过这个单view的视图文件xib是空的,它在MainViewController里添加了一个UIWebView,通过这个UIWebView来展现www里的html。
Phonegap的初始化过程包含JS端和Native端,这两端都是基于事件侦听的方式结合起来,JS端主要包含以下几个点:
- onDOMContentLoaded:dom载入完成
- onNativeReady:Native端WebUI载入完成
- onCordovaReady:JS端相关objects都创建完成
- deviceready:整个phonegap初始化完成
以上几个重要事件的先后顺序和hander侦听是通过channel组件架构,所谓的channel组件实际上就是phonegap自制的保障事件侦听和触发的组件,这块代码写得不错,短短2百多行代码,就打造了一个JS端事件侦听的框架,有兴趣的同学值得读一读。其中 onNativeReady是被native端调的,当native端WebUI初始化好后就会fire JS端onNativeReady事件,下面来看看native的几个关键的初始化节点:
- AppDelegate.didFinishLaunchingWithOptions:App启动,初始化controller和view
- CDVViewController.viewDidLoad:view加载,初始化WebView
- CDVViewController.webviewDidFinishLoad:WebView加载,触发JS端onNativeReady
Native端存在着App->view->webview三个层次,以上三个点正好对应着这三个层次的加载。
2)JS调用Native
IOS的UIWebViewDelegate提供了shouldStartLoadWithRequest方法,它能截获web端url请求,因此phonegap就是通过在web端构造一个不可见的iframe,并置其src为gap://ready,Native端截获这个请求后就会得知此时JS端有请求。这块代码可见"cordova/exec"模块:
- createGapBridge = function() {
- gapBridge = document.createElement("iframe");
- gapBridge.setAttribute("style", "display:none;");
- gapBridge.setAttribute("height","0px");
- gapBridge.setAttribute("width","0px");
- gapBridge.setAttribute("frameborder","0");
- document.documentElement.appendChild(gapBridge);
- }
JS端:
- cordova.commandQueue.push(JSON.stringify(command));
- if (cordova.commandQueue.length == 1 && !cordova.commandQueueFlushing) {
- if (!gapBridge) {
- createGapBridge();
- }
- gapBridge.src = "gap://ready";
- }
Native端:shouldStartLoadWithRequest
- if ([[url scheme] isEqualToString:@"gap"]) {
- [self flushCommandQueue];
- return NO;
- }
- - (void) flushCommandQueue
- {
- [self.webView stringByEvaluatingJavaScriptFromString:
- @"cordova.commandQueueFlushing = true"];
- // Keep executing the command queue until no commands get executed.
- // This ensures that commands that are queued while executing other
- // commands are executed as well.
- int numExecutedCommands = 0;
- do {
- numExecutedCommands = [self executeQueuedCommands];
- } while (numExecutedCommands != 0);
- [self.webView stringByEvaluatingJavaScriptFromString:
- @"cordova.commandQueueFlushing = false"];
- }
- - (int) executeQueuedCommands
- {
- // Grab all the queued commands from the JS side.
- NSString* queuedCommandsJSON = [self.webView stringByEvaluatingJavaScriptFromString:
- @"cordova.require('cordova/plugin/ios/nativecomm')()"];
- // Parse the returned JSON array.
- NSArray* queuedCommands =
- [queuedCommandsJSON cdvjk_objectFromJSONString];
- // Iterate over and execute all of the commands.
- for (NSString* commandJson in queuedCommands) {
- if(![self.commandDelegate execute:
- [CDVInvokedUrlCommand commandFromObject:
- [commandJson cdvjk_mutableObjectFromJSONString]]])
- {
- static NSUInteger maxLogLength = 1024;
- NSString* commandString = ([commandJson length] > maxLogLength) ?
- [NSString stringWithFormat:@"%@[...]", [commandJson substringToIndex:maxLogLength]] :
- commandJson;
- DLog(@"FAILED pluginJSON = %@", commandString);
- }
- }
- return [queuedCommands count];
- }
这几段代码就算没学过Objective-C也应该能猜出个大概,这也算是一个供应者和消费者模式的应用实例。
3)Native向JS返回结果
上段代码也透露了Native调用JS的方式:
- self.webView stringByEvaluatingJavaScriptFromString
- -(NSString*) toSuccessCallbackString: (NSString*) callbackId
- {
- NSString* successCB = [NSString stringWithFormat:@"cordova.callbackSuccess('%@',%@);", callbackId, [self toJSONString]];
- DLog(@"PluginResult toSuccessCallbackString: %@", successCB);
- return successCB;
- }
- -(NSString*) toErrorCallbackString: (NSString*) callbackId
- {
- NSString* errorCB = [NSString stringWithFormat:@"cordova.callbackError('%@',%@);", callbackId, [self toJSONString]];
- DLog(@"PluginResult toErrorCallbackString: %@", errorCB);
- return errorCB;
- }
到此,Phonegap在IOS平台上的实现比较关键的几个点已分析完,后面我会基于之前对android和wp源码分析一起,来看看这样的实现方式会有那些限制和性能损耗
- phonegap源码分析(三)------ IOS
- phonegap源码分析(三)------ IOS
- PhoneGap插件调用Java流程源码分析(三)
- phonegap源码分析(一)------ android
- phonegap源码分析(二)------ Windows Phone
- phonegap源码分析(一)------ android
- phonegap源码分析(一)------ android
- phonegap源码分析(二)------ Windows Phone
- phonegap源码分析(一)------ android
- phonegap源码分析(一)------ android
- 9 (phonegap源码分析)代码附录
- phonegap源码分析
- 1(phonegap源码分析)说明
- phonegap原理分析-ios版
- iOS版PhoneGap原理分析
- iOS版PhoneGap原理分析
- PhoneGap插件调用Java流程源码分析(一)
- PhoneGap插件调用Java流程源码分析(二)
- 我的php学习笔记(三十三)PHP中正则表达式学习及应用(一)
- 用序列化与反序列化实现深克隆
- php 函数总结
- phonegap源码分析(二)------ Windows Phone
- [面试tx] 根据上排给出十个数,在其下排填出对应的十个数
- phonegap源码分析(三)------ IOS
- 内存分配知识(全局,局部,静态变量)
- hdu2833
- jadclipse反编译时出现异常
- 放下我执
- selenium 初学一
- AndEngine引擎的生命周期
- Android源码编译问题汇总
- Github上README.md介绍