cordova与ios native code交互的原理

 

很早之前写了一篇博客,总结cordova插件怎么调用到原生代码: cordova调用过程,不过写得太水,基本没有提到原理。最近加深了一点理解,从新补充说明一下html

js调用native

下面是咱们产品中的代码片断:android

 

datePicker.show(options, function (date) {
    var month = date.getMonth() + 1;
    callback(null, date.getFullYear() + "-" + month + "-" + date.getDate());
});


cordova插件最终表现出来的都是js接口,而且调用者彻底不须要知道本身在调用一个cordova插件ios

 

可是在任何cordova js方法内部,最后必定会调用cordova.exec函数:web

 

cordova.exec(successCallback, errorCallback, "DatePicker", "show", []);

 

而后就进入了关键的cordova.exec函数,这是cordova框架的js端的最后一环,就是由它完成对ios native的调用框架

在exec函数里,首先会判断平台,多是android,ios或者wp,其余平台本文省略,若是是ios平台,cordova会采用如下2种方式的一种,来与ios native code交互异步

经过iframe

cordova.exec往当前的html中插入一个不可见的iframe,从而向UIWebView请求加载一个特殊的URL,这个URL里固然就包含了要调用的native plugin的类名,方法名,参数,回调函数等信息函数

接下来,因为被请求加载URL,因而UIWebViewDelegate的这个方法被调用:lua

 

- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType


这里就进入了native侧,从request里就拿到了js端传过来的信息,而后调用到native pluginspa

 

经过XHR

另外一种方式,cordova.exec里直接发起一个XHR请求,被native侧的NSURLProtocol拦截,因而调用到这个native方法:.net

 

+ (BOOL)canInitWithRequest:(NSURLRequest*)theRequest


也进入了native侧,而后以一样的方式调用到native plugin

 

在2种方式中,cordova会优先选择XHR方式,只有当XHR方式不可用时,才会使用iframe的方式。不过不管怎么样,这2种方法都为从js到native打开了一条通道,剩下的就是传递参数和路由的问题了

native调用js

另外一条通道就简单的多,由于iOS提供了原生支持,因此不须要想特别的办法。即经过UIWebView的这个方法:

 

- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;


看一下cordova框架native侧的代码,我去掉了注释和无关代码:

 

 

- (void)evalJsHelper:(NSString*)js
{
    if (![NSThread isMainThread] || !_commandQueue.currentlyExecuting) {
        [self performSelectorOnMainThread:@selector(evalJsHelper2:) withObject:js waitUntilDone:NO];
    } else {
        [self evalJsHelper2:js];
    }
}

 

- (void)evalJsHelper2:(NSString*)js
{
    NSString* commandsJSON = [_viewController.webView stringByEvaluatingJavaScriptFromString:js];
}


能够看到,正是经过UIWebView提供的这个方法完成的,可是,必定执行在main thread

 

同步和异步的问题

从上面的分析能够发现,从js调用native,2种方式都一定是异步的。而从native回到js,倒是一个同步的方法,并且是跑在主线程里

调用cordova插件的代码,对返回值的处理必定要放在回调函数里,由于结果是异步返回的。同时,回调函数的执行时间不能太长,不然会阻塞native主线程

参考

本文参考了如下2篇文章,都写得很好:

iOS版PhoneGap原理分析 

浅析Cordova for iOS 

相关文章
相关标签/搜索