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代碼回調JS1.在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];
四、總結:經上面的步驟,一個完整的互動流程就實作了。