扩展插件开发

以下为常见的三类插件:

Target TypeExtension point identifierScenarios
col 3 isright-aligned$1600
col 2 iscentered$12
zebra stripesare neat$1
Today Extensioncom.apple.widget-extension系统通知栏下拉显示
Share Extensioncom.apple.share-servicesHost App(照片、Safari、邮件、语音等)分享菜单第一行
Action Extension(UI)com.apple.ui-servicesHost App(照片、Safari、邮件、语音等)分享菜单第二行

这里写图片描述

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则架起了数据交互的鹊桥。

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时,扩展插件并未使能,需要到【更多】中打开开关。

5.插件如何调起Containing App?

鉴于很多同仁一再问起“ShareExtension 如何调起 Containing App?”这个问题,这里统一做个小结。
只有 Today Extension 才支持通过调用 -[NSExtensionContext openURL:completionHandler:] 访问 URL Scheme 链接打开 Containing App。
在 iOS 8.3 之前,Share/Action Extension 要想实现 URL Scheme,可通过创建一个 Sink UIWebVew (所谓“Sink”是指隐而不显,例如frame=CGRectZero)对 URL 进行 loadRequest 实现曲线救国。但是在 iOS 8.3 之后苹果在系统层面和评审阶段都枪毙了这种违规的做法。
根据苹果官方对 Share Extension 的原教旨,其被建议用于 Facebook/WeiBo 那种社交分享(social sharing websites)或 WeChat/WunderList 那种上传会话服务(upload services)场景,被设定(限定)在 Host App 弹出的模态窗口中轻量交互完成分享,不建议(禁止)调起 Containing App 这种大动作来完成分享任务!
答案:
1. 通过 ShareExtension 调起 Containing App 有违苹果官方规范,即使你调起了也通过不了评审,更何况它们已经在系统层面和技术层面屏蔽了这种行为!
2. ShareExtension 无法调起 Containing App !!!

三、插件的局限性

由此可见,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|NSExtensionActivationRule Dictionary可以配置插件支持的媒体类型及数量:

iOS扩展插件支持媒体类型配置键描述配置说明
NSExtensionActivationSupportsAttachmentsWithMaxCount附件最多限制20附件包括下面的File、Image和Movie三大类,单一、混选总量不超过20
NSExtensionActivationSupportsAttachmentsWithMinCount附件最少限制上面非零时,default=1默认至少选择1个附件,【分享】中才显示扩展插件图标
NSExtensionActivationSupportsImageWithMaxCount图片最多限制20单一、混选均不超过20
NSExtensionActivationSupportsMovieWithMaxCount视频最多限制20单一、混选均不超过20
NSExtensionActivationSupportsText文本类型default=0默认不支持文本分享,例如【备忘录】
NSExtensionActivationSupportsWebURLWithMaxCountWeb链接最多限制default=0默认不支持分享超链接,例如【Safari】
NSExtensionActivationSupportsWebPageWithMaxCountWeb页面最多限制default=0默认不支持Web页面分享,例如【Safari】

宿主应用(Host App)提供一个上下文(NSExtensionContext)向扩展(appex)传递数据,包含了待处理的数据(inputItems)。其传递的数据是一组NSExtensionItem对象,其中要分享的图片、视频、URL等附件就保存在NSExtensionItem的attachments数组中。

关于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标识的共享资源区—App Group 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编程指南》
《iOS8 Extensions》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值