注:本文为原创文章,欢迎转载,但是请注明出处:http://www.cnblogs.com/xdxer/p/4127220.html
一:什么是cordova插件
Plugin Development Guide : http://cordova.apache.org/docs/en/edge/guide_hybrid_plugins_index.md.html#Plugin%20Development%20Guide
cordova 官方的插件包含了很多调用硬件设备、文件系统和网络请求的功能。所以cordova的插件所提供的功能可以概括为:用native代码实现了某些功能,并且给javascript提供了相应可以方便地调用的接口。
(插件的运作方式待我有空我会做分析的,主要就是对CDV的一系列的类的源代码的分析)
二:一些小细节
# iOS插件是由继承自CDVPlugin类的类实现的。
#在JavaScript方面提供了统一的调用方法:
cordova.exec ( <successFunction>, // 正确的返回了那就运行该js function
<failFunction>, // 失败地返回的话就运行该方法
<serviceClass>, // 插件ObjC类
<actionMethod>, // 插件类中处理函数名字
[<args>] // 传递给插件的参数
);
从上面的结构我们可以进行一点猜测和分析:首先这些东西都会被装载在请求中,被UIWebViewDelegate中的一个处理请求的函数所处理,而且插件类和方法名都是通过字符串的方式进行传递的,所以可以大概猜测到cordova在底层实现中使用了objc_runtime 中的一些方法,比如objc_sendMsg,其实只要参考objc中的类是如何通过C语言中的结构体来表示的,就可以理解objc作为一个通过给对象传递消息来进行函数调用的语言的一个天生的优势了(当然调用的成本会很高,大多数时候可以用过IMP Caching方法进行效率上的优化)。再来看传递的参数,js所能传递的参数其实很简单,就那么几种,大多数都是字符串,要么就是一个对象,而对象又也许需要通过JSON来规范,而且偶尔也许会面临字符编码的问题(Unicode 万岁~)。
#在config.xml 插件属性中设置了 <param name =”onload” value = “true”/> 则可以在WebView load的时候进行对插件对象的初始化
#有的时候一个插件可能会运行很长时间( long-running request || background activity) 则需要实现onReset方法,当对javascript进行reload的时候就会调用(待研究)。
#可以使用block,在插件类中调用runInBackground。
三:Demo
首先在config.xml中加入这样的语句:
<feature name="PluginTest"> <param name="ios-package" value = "ASPPluginTest"/> </feature>
加入如下的插件类:
代码:
ASPPluginTest.h
// // ASPPluginTest.h // testCordova // // Created by Xia Dongxiang on 14-11-27. // Copyright (c) 2014年 Xia Dongxiang. All rights reserved. // #import <Cordova/CDVPlugin.h> @interface ASPPluginTest : CDVPlugin { } - (void) test:(CDVInvokedUrlCommand *) command; @end
ASPPluginTest.m
// // ASPPluginTest.m // testCordova // // Created by Xia Dongxiang on 14-11-27. // Copyright (c) 2014年 Xia Dongxiang. All rights reserved. // #import "ASPPluginTest.h" @implementation ASPPluginTest -(void) test:(CDVInvokedUrlCommand *)command { CDVPluginResult * pluginResult = nil; NSString * string = [command.arguments objectAtIndex:0]; if ([string isEqualToString:@"test"]) { pluginResult = [ CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:@"Test Successful!"]; } else pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"ERROR STRING!"]; [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; } @end
在JS方面,我们可以这样调用:
<script> var testPlugin = { success:function(string){ console.log(‘javascript success callback : ‘+string); }, fail:function(string){ console.log(‘javascript fail callback : ‘+string); }, test:function(){ cordova.exec(testPlugin.success,testPlugin.fail,"PluginTest","test",[‘test‘]); } }; </script> <br><br><br><br> <button type = "button" onclick="testPlugin.test();" >Test My Plugin</button>
其中,我们把exec方法封装了,并且把success 和 fail 都装入了一个对象中,是为了出于调用方便性和防止重命名的考虑。
效果如图:
调用成功!
如果也有提示说调用速度比较慢使用了18ms,那么我们就可以用上面提到过的方法去优化,使用block + commandDelegate 的runInBacnground方法去解决这个问题!