iOS Plugins
iOS Plugins
This section provides details for how to implement native plugin code on the iOS platform. Before reading this, see Application Plugins for an overview of the plugin's structure and its common JavaScript interface. This section continues to demonstrate the sample echo plugin that communicates from the Cordova webview to the native platform and back.
An iOS plugin is implemented as an Objective-C class that extends the CDVPlugin class. For JavaScript's exec method's service parameter to map to an Objective-C class, each plugin class must be registered as a <feature> tag in the named application directory's config.xml file.
Plugin Class Mapping
The JavaScript portion of a plugin uses the cordova.exec method as follows:
exec(<successFunction>, <failFunction>, <service>, <action>, [<args>]);
This marshals a request from the UIWebView to the iOS native side, effectively calling the action method on the serviceclass, with the arguments passed in the args array.
Specify the plugin as a <feature> tag in your Cordova-iOS application's project's config.xml file, using the plugin.xmlfile to inject this markup automatically, as described in Application Plugins:
<feature name="LocalStorage">
<param name="ios-package" value="CDVLocalStorage" />
</feature>
The feature's name attribute should match what you specify as the JavaScript exec call's service parameter. The valueattribute should match the name of the plugin's Objective-C class. The <param> element's name should always be ios-package. If you do not follow these guidelines, the plugin may compile, but Cordova may still not be able to access it.
Plugin Initialization and Lifetime
One instance of a plugin object is created for the life of each UIWebView. Plugins are ordinarily instantiated when first referenced by a call from JavaScript. Otherwise they can be instantiated by setting a param named onload to true in the config.xml file:
<feature name="Echo">
<param name="ios-package" value="Echo" />
<param name="onload" value="true" />
</feature>
There is no designated initializer for plugins. Instead, plugins should use the pluginInitialize method for their startup logic.
Plugins with long-running requests, background activity such as media playback, listeners, or that maintain internal state should implement the onReset method to clean up those activities. The method runs when the UIWebView navigates to a new page or refreshes, which reloads the JavaScript.
Writing an iOS Cordova Plugin
A JavaScript call fires off a plugin request to the native side, and the corresponding iOS Objective-C plugin is mapped properly in the config.xml file, but what does the final iOS Objective-C plugin class look like? Whatever is dispatched to the plugin with JavaScript's exec function is passed into the corresponding plugin class's action method. A plugin method has this signature:
- (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];
}
For more details, see [CDVInvokedUrlCommand.h](https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/CDVInvokedUrlCommand.h), [CDVPluginResult.h](https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/CDVPluginResult.h), and[CDVCommandDelegate.h](https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/CDVCommandDelegate.h).
iOS CDVPluginResult Message Types
You can use CDVPluginResult to return a variety of result types back to the JavaScript callbacks, using class methods that follow this pattern:
+ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAs...
You can create String, Int, Double, Bool, Array, Dictionary, ArrayBuffer, and Multipart types. You can also leave out any arguments to send a status, or return an error, or even choose not to send any plugin result, in which case neither callback fires.
Note the following for complex return values:
- messageAsArrayBuffer expects NSData* and converts to an ArrayBuffer in the JavaScript callback. Likewise, any ArrayBuffer the JavaScript sends to a plugin are converted to NSData*.
- messageAsMultipart expects an NSArray* containing any of the other supported types, and sends the entire array as the arguments to your JavaScript callback. This way, all of the arguments are serialized or deserialized as necessary, so it is safe to return NSData* as multipart, but not as Array/Dictionary.
Echo iOS Plugin Example
To match the JavaScript interface's echo feature described in Application Plugins, use the plugin.xml to inject a featurespecification to the local platform's config.xml file:
<platform name="ios">
<config-file target="config.xml" parent="/*">
<feature name="Echo">
<param name="ios-package" value="Echo" />
</feature>
</config-file>
</platform>
Then we would add the following Echo.h and Echo.m files to the Plugins folder within the Cordova-iOS application directory:
/********* Echo.h Cordova Plugin Header *******/
#import <Cordova/CDV.h>
@interface Echo : CDVPlugin
- (void)echo:(CDVInvokedUrlCommand*)command;
@end
/********* Echo.m Cordova Plugin Implementation *******/
#import "Echo.h"
#import <Cordova/CDV.h>
@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
The necessary imports at the top of the file extends the class from CDVPlugin. In this case, the plugin only supports a single echo action. It obtains the echo string by calling the objectAtIndex method get the first parameter of the arguments array, which corresponds to the arguments passed in by the JavaScript exec() function.
It checks the parameter to make sure it is not nil or an empty string, returning a PluginResult with an ERROR status if so. If the parameter passes the check, it returns a PluginResult with an OK status, passing in the original echo string. Finally, it sends the result to self.commandDelegate, which executes the exec method's success or failure callbacks on the JavaScript side. If the success callback is called, it passes in the echo parameter.
iOS Integration
The CDVPlugin class features other methods that your plugin can override. For example, you can capture the pause, resume, app terminate and handleOpenURL events. See the CDVPlugin.h and CDVPlugin.m class for guidance.
Threading
Plugin methods ordinarily execute in the same thread as the main interface. If your plugin requires a great deal of processing or requires a blocking call, you should use a background thread. For example:
- (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];
}];
}
Debugging iOS Plugins
To debug on the Objective-C side, you need Xcode's built-in debugger. For JavaScript, on iOS 5.0 you can use Weinre, an Apache Cordova Project or iWebInspector, a third-party utility. For iOS 6, you can attach Safari 6.0 to the app running within the iOS 6 Simulator.
Common Pitfalls
- Don't forget to add your plugin's mapping to config.xml. If you forget, an error is logged in the Xcode console.
- Don't forget to add any hosts you connect to in the whitelist, as described in Domain Whitelist Guide. If you forget, an error is logged in the Xcode console.
iOS Plugins的更多相关文章
- iOS 混合开发之 Cordova 实践
在15年时,之前公司使用 Cordova 做混合开发使用,后来公司没有用到了,现在重新记录下. Cordova (官网:http://cordova.apache.org/)简介: Apache Co ...
- Cordova学习(一) 环境搭建
一.什么是cordova Cordova提供了一组设备相关的API,通过这组API,移动应用能够以JavaScript访问原生的设备功能,如摄像头.麦克风等. Cordova还提供了一组统一的Java ...
- mobile web retina 下 1px 边框解决方案
本文实际上想说的是ios8下 1px解决方案. 1px的边框在devicePixelRatio = 2的retina屏下会显示成2px,在iphone 6 plug 下,更显示成3px.由其影响美感. ...
- Cordova CLI源码分析(一)——简介
本系列文章分析基于node.js的命令行工具Cordova CLI,所以如果对node.js基础不是很了解,建议参考http://nodejs.gamesys.net/node-js提供的基础教程 文 ...
- ionic4+angular6 混合移动开发 capacitor cordova
首先要更新或者安装 ionic cli npm install -g ionic 创建项目 ionic start ionic-angular tabs --type=angular –type=an ...
- 自定义 Cordova插件详解
一.Cordova的基础点 在混合式应用中,我们通过现有的Cordova插件,可以轻松的在 H5 上调用手机native的功能.现有的Cordova插件能满足平时大部分的开发需求,然而,有时候找不到合 ...
- 自定义Cordova插件详解
一.Cordova的基础点 在混合式应用中,我们通过现有的Cordova插件,可以轻松的在 H5 上调用手机native的功能.现有的Cordova插件能满足平时大部分的开发需求,然而,有时候找不到合 ...
- 再谈mobile web retina 下 1px 边框解决方案
本文实际上想说的是ios8下 1px解决方案. 1px的边框在devicePixelRatio = 2的retina屏下会显示成2px,在iphone 6 plug 下,更显示成3px.由其影响美感. ...
- Ionic3 demo TallyBook 实例1
1.创建项目 ionic start TallyBook blank 创建一个空的项目 ionic cordova platform add android 添加andorid平台 io ...
随机推荐
- DataSet、DataTable、DataRow 复制
DataSet.DataTable.DataRow 复制 DataSet 对象是支持 ADO.NET的断开式.分布式数据方案的核心对象 ,用途非常广泛.我们很多时候需要使用其中的数据,比如取得一个Da ...
- 重复弹Toast的解决方案
虽然网上有很多了,还是记录一下吧, 解决思路:不用计算Toast的时间之类的,就是定义一个全局的成员变量Toast, 这个Toast不为null的时候才去make,否则直接setText.为了按返回键 ...
- MarkDown/reST 文档发布流水线
相信很多朋友都在使用Markdown或者restructuredText格式来编写一些技术文档,也会把这些文档放在github上分享给社区.GitHub提供了很好的Markdown格式解析支持,但是这 ...
- HQL练习
Hive学习笔记总结 05. Hql练习 1. hql基础练习 题目和数据来源:http://www.w2b-c.com/article/150326(去掉-) create和load create ...
- PHP里文件的查找方式及写法
PHP里说的文件包括:文件和目录1.用filetype方法加路径("./11.txt")是判断文件类型 //var_dump(filetype("./11.txt&quo ...
- LeetCode题解 15题 第二篇
之前写过一篇,这是第二篇.上一篇用了多种编程语言来做,这一次是以学算法为主,所以打算都用python来完成. 4. Median of Two Sorted Arrays There are two ...
- 自定义session扫描器
为何要自定义session扫描器 由于服务器来管理session的销毁不怎么靠谱,因此很多网站都会自己定义一个session扫描器来管理session的创建和销毁. 实现思路 首先,创建一个sessi ...
- 一个简单的使用restc demo
最近不经意间看到饿了么团队开发的restc,接口调试工具(类似postman),其实调试接口都没用过工具,每次都只是运行起项目直接调接口.闲来无事,看到restc,就决定试试,后面觉得挺不错的,就分享 ...
- Java定时器Timer简述
概述 主要用于Java线程里指定时间或周期运行任务.Timer是线程安全的,但不提供实时性(real-time)保证. 构造函数 Timer() 默认构造函数. Timer(boolean) 指定关联 ...
- PostgreSQL Replication之扩展与BDR
在这一章中,将向您介绍一个全新的技术,成为BDR.双向复制(BDR),在PostgreSQL的世界里,它绝对是一颗冉冉升起的新星.在不久的将来,许多新的东西将会被看到,并且人们可以期待一个蓬勃发展的项 ...