iOS8扩展插件Extension的开发
2015-08-13 14:48
561 查看
一.iOS8扩展插件概述
WWDC14除了发布了OS X v10.10和switf外,iOS8.0也开始变得更加开放了。说到开放,当然要数应用扩展(App Extension)了。顾名思义,应用扩展允许开发者扩展应用的自定义功能和内容,能够让用户在使用其他应用程序时使用该项功能,从而实现各个应用程序间的功能和资源共享。可以将扩展理解为一个轻量级(nimbleand lightweight)的分身。
以下为常见的三类插件:
Target Type | Extension point identifier | Scenarios |
Today Extension | com.apple.widget-extension | 系统通知栏下拉显示 |
Share Extension | com.apple.share-services | Host App(照片、Safari、邮件、语音等)分享菜单第一行 |
Action Extension(UI) | com.apple.ui-services | Host App(照片、Safari、邮件、语音等)分享菜单第二行 |
例如【微信】最多支持分享9张(NSExtensionActivationSupportsImageWithMaxCount=9)照片给好友或到朋友圈。
二.插件工作机制
1.插件只能与Host App通过上下文直接通信
2.插件可通过共享资源区与Containing App间接通信
3.Host App-Extension-Containing App工作流程
Host App通过点击系统分享菜单中的插件图标调起扩展程序——Share/ActionExtension (*.appex)。iOS系统(Host App)通过扩展上下文(NSExtensionContext)向Share/ActionExtension传递欲分享的数据。
Share/Action Extension提取数据并序列化到以AppGroup ID标识的共享资源区NSUserDefaults/AppGroup Container(containerURLForSecurityApplicationGroupIdentifier)中。
Share/Action Extension通过URL
Scheme呼起ContainingApp,同时插件通过上下文向iOS系统(HostApp)发出request completion通知,以便返回到Host App(iOS系统会dismiss插件UIViewController)。
Containing App通过App Group ID从NSUserDefaults/containerURL中读取分享过来的数据,并对分享数据进行后续处理。
由此可见,扩展插件将Host App与Containing App勾搭起来,而App Group Container则架起了数据交互的鹊桥。
这里需要注意的是,在iOS 8.0中,只有Today Extension才支持直接调用NSExtensionContext的openURL:completionHandler:打开URL链接;Share/Action
Extension要想实现URL Scheme,只能创建一个SinkUIWebVew对URL进行loadRequest实现曲线救国(所谓“Sink”是指隐而不显,例如frame=CGRectZero)。
4.插件的UI形态
插件在UI上以UIViewController模式存在,被parentViewController(Host App)以模态窗口形式弹出(present as modal viewController)。插件工程在Info.plist的NSExtension中通过NSExtensionMainStoryboard指定UI视图入口。当然,如果不想使用storyboard,也可以使用NSExtensionPrincipalClass指定自定义UIViewController子类名(也可以封装到UINavigationController)。
注意:
新建Extension Target后(Deployment Target≥8.0),需在Build Settings|Architectures|Valid Architectures中增加arm64!
初始安装Containing App时,扩展插件并未使能,需要到【更多】中打开开关。
三.插件的局限性
以下文字节选自《App Extension Programming Guide》,主要列举了插件的局限性,以知其可为不可为。--------------------------------------------------------------------------------
1.Design a Streamlined UI
An extension`s UI should be simple, restrained,and focused on facilitating a single task.
To improve performance and the user`s experience, avoid including extraneous UI
that doesn`t support your extension`s main task.
2.Optimize Efficiency and Performance
(1)App extensions should feel nimble and lightweight tousers.
Design your app extension to launch quickly, aiming
for well under one second.
An extension that launches too slowly is terminated by
the system.
(2)Memory limits for running app extensions are significantly lower than
the memory limits imposed on a foreground app.
On both platforms, the system may aggressively terminate extensions
because users want to return to their main goal in the host app.
Some extensions may have lower memory limits than others.
(3)Your app extension doesn`t own the main run loop, so it`s crucial
that you follow the established rules for good behavior in main runloops.
For example, if your extension blocks the main runloop,
it can create a bad user experience in another extension or app.
(4)Keep in mind that theGPU is a shared resource in the system.
App extensions do not get top priority for shared resources; for example, a Today widget that runs a graphics-intensive game might give users a bad experience. The
system is likely to terminate such an extension because of memory pressure.
Functionality that makes heavy use of system resources is appropriate for an app, not an app extension.
--------------------------------------------------------------------------------
由此可见,iOS系统对插件要求简洁至上:UI启动要快、内存消耗要少、runloop执行耗时要短。
iOS系统对插件的限制决定了开发的插件必须轻量,发点Twitter/微博分享、小图片文件分享、URL跳转还是可以的;奢望丰富绚丽的UI或者用来传大文件等大动作是不合适的。
当然,如果希望扩展(即使退出)执行长时间任务(比如上传/下载),可以使用NSURLSession来创建一个上传/下载session,并初始化一个后台上传/下载任务。
注意:
Apple也限制了扩展在API使用方面的权限,在扩展中禁用的API原型声明被标上了NS_EXTENSION_UNAVAILABLE宏。例如:
+ (UIApplication*)sharedApplication NS_EXTENSION_UNAVAILABLE_IOS;
对sharedApplication的限制实际上就是不让插件直接获取访问宿主应用(Host App的UIApplication)对象。
四.Share/Action扩展插件支持的媒体类型配置
Info.plist中的NSExtension|NSExtensionAttributes|NSExtensionActivationRuleDictionary可以配置插件支持的媒体类型及数量:
iOS扩展插件支持媒体类型配置键 | 描述 | 配置 | 说明 |
NSExtensionActivationSupportsAttachmentsWithMaxCount | 附件最多限制 | 20 | 附件包括下面的File、Image和Movie三大类,单一、混选总量不超过20 |
NSExtensionActivationSupportsAttachmentsWithMinCount | 附件最少限制 | 上面非零时,default=1 | 默认至少选择1个附件,【分享】中才显示扩展插件图标 |
NSExtensionActivationSupportsFileWithMaxCount | 文件最多限制 | 20 | 文件泛指除Image/Movie之外的附件,例如【邮件】附件、【语音备忘录】等。 单一、混选均不超过20。 |
NSExtensionActivationSupportsImageWithMaxCount | 图片最多限制 | 20 | 单一、混选均不超过20 |
NSExtensionActivationSupportsMovieWithMaxCount | 视频最多限制 | 20 | 单一、混选均不超过20 |
NSExtensionActivationSupportsText | 文本类型 | default=0 | 默认不支持文本分享,例如【备忘录】 |
NSExtensionActivationSupportsWebURLWithMaxCount | Web链接最多限制 | default=0 | 默认不支持分享超链接,例如【Safari】 |
NSExtensionActivationSupportsWebPageWithMaxCount | Web页面最多限制 | default=0 | 默认不支持Web页面分享,例如【Safari】 |
关于UTIs,参考UniformType Identifiers
Reference | System-Declared Uniform Type Identifiers。
媒体类型 | 文件UTI |
图片(public.image) | kUTTypeImage kUTTypeJPEG kUTTypePNG kUTTypeGIF kUTTypeTIFF kUTTypeBMP kUTTypeICO |
视频(public.movie) | kUTTypeMovie kUTTypeQuickTimeMovie kUTTypeMPEG kUTTypeMPEG4 kUTTypeAVIMovie @"public.3gpp" @"com.real.realmedia" @"com.microsoft.windows-media-wmv" @"com.microsoft.advanced-systems-format" |
音频(public.audio) | kUTTypeAudio kUTTypeMP3 kUTTypeMPEG4Audio kUTTypeWaveformAudio @"com.microsoft.windows-media-wma" |
文档 | kUTTypePDF @"com.microsoft.word.doc" @"com.microsoft.excel.xls" kUTTypePresentation @"com.microsoft.powerpoint.ppt" @"com.apple.keynote.key" |
压缩包 | kUTTypeZipArchive kUTTypeGNUZipArchive kUTTypeBzip2Archive @"public.tar-archive" @"org.gnu.gnu-zip-tar-archive" |
五.插件与Containing App的App
Group证书配置
Containing App及其Extension是通过以App Group ID标识的共享资源区—AppGroup Container来实现数据共享的。
Containing App及其Extension的App ID必须是Explicit,且Extension App ID必须以Containing App
ID为Prefix/Seed,并且配置到同一App Group下。
App ID配置到Info.plist的BundleIdentifier中;App Group在target的【Xcode
Target|Capabilities】中启用,配置到【Xcode Target|Build Settings|Code Signing|Code Signing Entitlements】中的*.entitlements文件的com.apple.security.application-groups
键中。
证书和Provisioning Profile的申请以及Code Signing配置流程同以前普通的App,详情请参考《iOS开发证书要点详解》。
六.Containing App的Build Phases配置(embed app extensions)
Containing App 的【Xcode target|BuildPhases|Target Dependencies】中可以添加或移除插件target。Containing App 的【Xcode target|BuildPhases|Embed App Extensions】下Destination为Plugins中可以添加或移除插件product(*.appex)。
注意:默认了勾选“Copy only when installing”,表示从AppStore安装(包括升级覆盖)时才拷贝插件。Xcode连接真机调试时,需取消该改项,否则系统【分享】菜单中不会出现插件!
参考:
《App
Extension Programming Guide》/《App Extension编程指南》
《App
Extensions for iOS 8 in Depth》
《iOS8
Extensions》《iOS8通知中心扩展制作入门》
《iOS
8.0 Action Extension icon is blank on device which fixed in iOS 8.1》
相关文章推荐
- ios接入facebook及集成plugin-x
- iOS中关于登录验证方面的问题的解决
- [iOS]字符串转字典
- 【转】iOS调试技巧
- iOS第三方支付-支付宝支付
- 4000 获取键盘的高度变化
- IOS 将毫秒数转换为年月日时分秒的时间
- 关于iOS中的懒加载
- iOS 集合的深复制与浅复制
- iOS利用Runtime自定义控制器POP手势动画(经典)
- iOS 之GCD串行和并发队列的理解
- iOS学习过程中遇到的一些有用的小功能(8/13更新)
- iostream.h和iostream 区别
- 一个phonegap门外汉的phonegap初体验
- 一个phonegap门外汉的phonegap初体验
- ios x264编译问题 No working C compiler found
- IOS下Category添加属性字段
- ios 打开图片库和相机选择图片界面修改为简体中文
- 千锋扣丁学堂 如何学习iOS
- 实际iOS编程中遇到的自定义导航栏按钮,导致手势返回失效的解决方法