天天看點

[Cordova]JS和Native互動實作關鍵代碼(iOS)

一、JS中定義的exec函數:

define("cordova/exec", function(require, exports, module) 。關鍵實作代碼如下:

1.建立command對象,并且将指令推入commandQueue var command = [callbackId, service, action, actionArgs]; commandQueue.push(JSON.stringify(command));

2.建立不可見的iframe,并且在後續會将此iframe添加的頁面 function createExecIframe() {     var iframe = document.createElement("iframe");     iframe.style.display = 'none';     document.body.appendChild(iframe);     return iframe; }

3.将iframe的連結設定為“gap://ready”,此時網頁端會發送一個請求 execIframe = execIframe || createExecIframe(); execIframe.src = "gap://ready";

二、UIWebView中攔截請求

1.CDVViewController中,實作了webview的代理方法: - (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType

2.當網頁端發起iframe中的請求時,請求會被此方法攔截: if ([[url scheme] isEqualToString:@"gap"]) {     [_commandQueue fetchCommandsFromJs];     return NO; } 當發現網頁連結是gap協定的,此時通過fetchCommandsFromJs方法擷取指令對象并執行,并且傳回NO。實作的效果:既攔截了指令,而且頁面不做變化。

2.fetchCommandsFromJs實作

(1)通過執行js腳本,擷取網頁端js對象commandQueue中的指令(轉換為Json的字元串格式,包含服務名,方法名,以及參數清單) NSString* queuedCommandsJSON = [_viewController.webView stringByEvaluatingJavaScriptFromString:    @"cordova.require('cordova/exec').nativeFetchMessages()"];     (2)将json字元串解析,并且合成CDVInvokedUrlCommand對象 NSArray* commandBatch = [queuedCommandsJSON JSONObject]; CDVInvokedUrlCommand* command = [[CDVInvokedUrlCommand alloc] initFromJson:commandBatch];

(3)執行Command對象 //通過類名擷取plugin執行個體 CDVPlugin* obj = [_viewController.commandDelegate getCommandInstance:command.className]; //通過方法名建立方法對象 SEL normalSelector = NSSelectorFromString(methodName); //通過參數字元串清單建立參數清單對象 NSMutableArray* arguments = nil; NSMutableDictionary* dict = nil; [command legacyArguments:&arguments andDict:&dict]; //發送消息 objc_msgSend(obj, legacySelector, arguments, dict);

三、Native代碼回調JS

1.在plugin的功能方法實作中,我們手動調用如下函數向js頁面傳回結果 [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];

2.在如上方法的實作中,實作如下: NSString* js = [NSString stringWithFormat:@"cordova.require('cordova/exec').nativeCallback('%@',%d,%@,%d)", callbackId, status, argumentsAsJSON, keepCallback]; [_viewController.webView stringByEvaluatingJavaScriptFromString:js];

四、總結:經上面的步驟,一個完整的互動流程就實作了。