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 

相關文章
相關標籤/搜索