[Cordova]JS和Native互動實現關鍵程式碼(iOS)
阿新 • • 發佈:2019-02-01
一、JS中定義的exec函式:define("cordova/exec", function(require, exports, module) 。關鍵實現程式碼如下:1.建立command物件,並且將命令推入commandQueuevar 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];四、總結:經上面的步驟,一個完整的互動流程就實現了。