翻译自cordova官方文档(如果需要链接,请自行对照原文链接进行查看):
https://cordova.apache.org/docs/en/latest/guide/platforms/ios/plugin.html
本章节针对如何开发基于iOS系统的插件进行介绍,在此之前,请阅读Plugin Development Guide(插件开发指南)对插件的结构和JavaScript接口有一个大概的了解。
iOS插件是以继承至CDVPlugin类Objective-C的子类来实现的,通过JavaScript的exec函数来将service/parameter映射到Objective-C类,每一个插件在工程根目录下的config.xml文件中通过标签进行注册。
我们通过如下的Cordova API来实现JavaScript到Objective-C的映射过程:
exec(<successFunction>, <failFunction>, <service>, <action>, [<args>]);
通过这个JavaScript函数我们就可以使用JavaScript代码来执行Objective-C类的指定函数,并且通过args来传递参数。
通过config.xml中iOS平台的标签来指定需要的插件,通过plugin.xml文件来自动注入插件到iOS平台代码中去。
"LocalStorage">"ios-package"value="CDVLocalStorage" />
标签的name属性用于指定plugin在JavaScript执行exec方法时service参数的值,为标签内标签内value对应的Objective-C类的具体函数名,args以数组的形式传入到Objective-C函数内。的name字段永远为’ios-package’。
plugin对象的生命周期和UIWebView是一致的,Plugin是不需要实例化的,在他们第一次被调用的时候会自动实例化。也可以通过指定的方式来手动实例化一个plugin比如:
"Echo">"ios-package"value="Echo" />"onload"value="true" />
当使用的时候,在程序启动的时候会执行插件的pluginInitialize方法来实例化一个插件类对象。你可以通过覆盖pluginInitialize方法的方式在程序启动的时候为你的插件做点什么。
Plugin进行耗时操作的时候,比如媒体操作,监听,或者网络状态相关的事情,应该提供重置和取消操作来终止之前的操作或者请求。当需要转入新的页面或者刷新页面这种需要重新加载JavaScript的时候被使用。
JavaScript通过config.xml配置的映射来发起一个plugin请求来执行Objective-C代码,但是最终的Objective-C插件类什么样呢?下面就是plugin的一个方法定义:
- (void)myMethod:(CDVInvokedUrlCommand*)command
{
CDVPluginResult* pluginResult = nil;
NSString* myarg = [command.arguments objectAtIndex:0];
if (myarg != nil) {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
} else {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Arg was null"];
}
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
更多的信息可以查看CDVInvokedUrlCommand.h, CDVPluginResult.h, CDVCommandDelegate.h这三个Cordova源代码文件。
你可以使用CDVPluginResult类来返回各种类型的结果信息给JavaScript的回调函数,通过以下的方式来创建一个CDVPluginResult对象:
+ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAs...
你可以返回字符串,整数,布尔,数组以及复合数据类型等,你也可以仅仅返回一个状态信息或者错误信息,当然你也可以不返回任何信息仅仅调用JavaScript端的回调函数。
下面复杂类型的返回值的使用方法:
messageAsArrayBuffer以NSData的形式被传送到JavaScript回调函数,并且被转换为ArrayBuffer类型,而ArrayBuffer在传入到Objective-C端的时候会被转换成NSData。
messageAsMultipart以NSArray的形式被传入到JavaScript回调函数,里面包含各种类型的数据对象。通过这种方式传送数据,里面的数据会被序列化和反序列化,所以他可以安全的返回NSData,而不是Array/Dictionary。
Echo iOS Plugin(这篇文章对于plugin的配置在使用cordova build命令以后会被覆盖,不建议在iOS工程直接加入文件修改配置文件信息的方式添加插件。使用独立插件通过plugin add的方式添加插件比较容易维护和使用)
这个例子通过plugin.xml来向指定的iOS平台注入信息。
"ios">"config.xml"parent="/*">"Echo">"ios-package"value="Echo" />file>platform>
添加Echo.h文件和Echo.m文件到iOS镜像的文件夹的Plugins文件夹:
/********* Echo.h Cordova Plugin Header *******/#import
@interface Echo : CDVPlugin
- (void)echo:(CDVInvokedUrlCommand*)command;
@end
/********* Echo.m Cordova Plugin Implementation *******/#import "Echo.h"#import
@implementation Echo
- (void)echo:(CDVInvokedUrlCommand*)command
{
CDVPluginResult* pluginResult = nil;
NSString* echo = [command.arguments objectAtIndex:0];
if (echo != nil && [echo length] > 0) {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:echo];
} else {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
}
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
@end
上面的类继承至CDVPlugin类,在这里,Echo插件只有一个功能。就是返回JavaScript传入的第一个参数内容。如果没有传入参数则返回错误,如果传入参数,则将该参数返回。
CDVPlugin类包含其他的一些方法,你可以通过重写的方式来实现自己的行为,比如捕获pause,resume等等。具体可以去读CDVPlugin.h/CDVPlugin.m源文件
我们在plugin里面经常需要做一些耗时的操作,但是在主线程耗时过长,App就会被系统kill。所以通过runInBackground来进行耗时操作:
- (void)myPluginMethod:(CDVInvokedUrlCommand*)command
{
// Check command.arguments here.
[self.commandDelegate runInBackground:^{
NSString* payload = nil;
// Some blocking logic...
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:payload];
// The sendPluginResult method is thread-safe.
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}];
}
使用Xcode来调试plugin,如果调试JavaScript代码,需要使用Safari在虚拟机或者设备上调试。
不要忘记在config.xml添加映射信息。