[Cordova]JS和Native交互实现关键代码(iOS)

来源:互联网 发布:php soap 传xml 编辑:程序博客网 时间:2024/05/22 04:57
一、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];

四、总结:经上面的步骤,一个完整的交互流程就实现了。
0 0
原创粉丝点击