js与nativede 通信
- - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
- /*
- * 方法的返回值是BOOL值。
- * 返回YES:表示让浏览器执行默认操作,比如某个a链接跳转
- * 返回NO:表示不执行浏览器的默认操作,这里因为通过url协议来判断js执行native的操作,肯定不是浏览器默认操作,故返回NO
- * /
- - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
- NSURL *url = [request URL];
- if ([[url scheme] isEqualToString:@"callFunction") {
- //调用原生方法
- return NO;
- } else if (([[url scheme] isEqualToString:@"sendEvent") {
- //触发事件
- return NO;
- } else {
- return YES;
- }
- }
- [webView stringByEvaluatingJavaScriptFromString:@"alert(‘hello world!‘)"];
- 这里有个很重要的事需要说明一下:
- 目前PhoneGap的文档更新非常不及时,特别是插件的使用方面,比如Dialog插件的使用,文档中写的是使用navigator.notification.alert,但是经过我的摸索,因为现在PhoneGap使用AMD的方式来管理插件,所以应该是使用cordova.require("cordova/plugin/notification").alert的方式来调用。
- 插件的合并方面,也有很多坑,主要是文档不全 - -|||
- function alertDismissed() {
- // do something
- }
- function showAlert() {
- cordova.require("cordova/plugin/notification").alert(
- ‘You are the winner!‘, // message
- alertDismissed, // callback
- ‘Game Over‘, // title
- ‘Done‘ // buttonName
- );
- }
- var exec = cordova.require(‘cordova/exec‘);
- var platform = cordova.require(‘cordova/platform‘);
- module.exports = {
- /**
- * Open a native alert dialog, with a customizable title and button text.
- *
- * @param {String} message Message to print in the body of the alert
- * @param {Function} completeCallback The callback that is called when user clicks on a button.
- * @param {String} title Title of the alert dialog (default: Alert)
- * @param {String} buttonLabel Label of the close button (default: OK)
- */
- alert: function(message, completeCallback, title, buttonLabel) {
- var _title = (title || "Alert");
- var _buttonLabel = (buttonLabel || "OK");
- exec(completeCallback, null, "Notification", "alert", [message, _title, _buttonLabel]);
- }
- }
- ....
- define("cordova/exec", function(require, exports, module) {
- ...
- function iOSExec() {
- ...
- var successCallback, failCallback, service, action, actionArgs, splitCommand;
- var callbackId = null;
- ...
- // 格式化传入参数
- successCallback = arguments[0]; //成功的回调函数
- failCallback = arguments[1]; //失败的回调函数
- service = arguments[2]; //表示调用native类的类名
- action = arguments[3]; //表示调用native类的一个方法
- actionArgs = arguments[4]; //参数
- //默认callbackId为‘INVALID‘,表示不需要回调
- callbackId = ‘INVALID‘;
- ...
- //如果传入参数有successCallback或failCallback,说明需要回调,就设置callbackId,并存储对应的回调函数
- if (successCallback || failCallback) {
- callbackId = service + cordova.callbackId++;
- cordova.callbacks[callbackId] =
- {success:successCallback, fail:failCallback};
- }
- //格式化传入的service、action、actionArgs,并存储,准备native代码来调用
- actionArgs = massageArgsJsToNative(actionArgs);
- var command = [callbackId, service, action, actionArgs];
- commandQueue.push(JSON.stringify(command));
- ...
- //通过创建一个iframe并设置src,给native代码一个指令,开始执行js调用native的过程
- execIframe = execIframe || createExecIframe();
- if (!execIframe.contentWindow) {
- execIframe = createExecIframe();
- }
- execIframe.src = "gap://ready";
- ...
- }
- module.exports = iOSExec;
- });
- - (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
- {
- NSURL* url = [request URL];
- /*
- * 判断url的协议以"gap"开头
- * 执行在js端调用cordova.exec()的command队列
- * 注:这里的command表示js调用native
- */
- if ([[url scheme] isElaqualToString:@"gap"]) {
- //_commandQueue即CDVCommandQueue类
- //从js端拉取command,即存储在js端commandQueue数组中的数据
- [_commandQueue fetchCommandsFromJs];
- //开始执行command
- [_commandQueue executePending];
- return NO;
- }
- ...
- }
- - (void)fetchCommandsFromJs
- {
- // 获取js端存储的command,并在native暂存
- NSString* queuedCommandsJSON = [_viewController.webView stringByEvaluatingJavaScriptFromString:
- @"cordova.require(‘cordova/exec‘).nativeFetchMessages()"];
- [self enqueueCommandBatch:queuedCommandsJSON];
- }
- - (void)executePending
- {
- ...
- //_queue即command队列,依次执行
- while ([_queue count] > 0) {
- ...
- //取出从js中获取的command字符串,解析为native端的CDVInvokedUrlCommand类
- CDVInvokedUrlCommand* command = [CDVInvokedUrlCommand commandFromJson:jsonEntry];
- ...
- //执行command
- [self execute:command])
- ...
- }
- }
- - (BOOL)execute:(CDVInvokedUrlCommand*)command
- {
- ...
- BOOL retVal = YES;
- //获取plugin对应的实例
- CDVPlugin* obj = [_viewController.commandDelegate getCommandInstance:command.className];
- //调用plugin实例的方法名
- NSString* methodName = [NSString stringWithFormat:@"%@:", command.methodName];
- SEL normalSelector = NSSelectorFromString(methodName);
- if ([obj respondsToSelector:normalSelector]) {
- //消息发送,执行plugin实例对应的方法,并传递参数
- objc_msgSend(obj, normalSelector, command);
- } else {
- // There‘s no method to call, so throw an error.
- NSLog(@"ERROR: Method ‘%@‘ not defined in Plugin ‘%@‘", methodName, command.className);
- retVal = NO;
- }
- ...
- return retVal;
- }
- - (void)alert:(CDVInvokedUrlCommand*)command
- {
- NSString* callbackId = command.callbackId;
- NSString* message = [command argumentAtIndex:0];
- NSString* title = [command argumentAtIndex:1];
- NSString* buttons = [command argumentAtIndex:2];
- [self showDialogWithMessage:message title:title buttons:@[buttons] defaultText:nil callbackId:callbackId dialogType:DIALOG_TYPE_ALERT];
- }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。