前言
本篇文章是对 iOS Application Extension 的简介。介绍的内容包括:对
Application Extension 的种类、运行原理、声明周期、之间的通信等。
Application Extension
Application Extension 是从 iOS 8 开始引入的一个新特性。Application Extension扩展可以在原有的应用基础之上,延伸应用的功能,扩大应用的显示内容。可以让用户与其他应用或者系统来进行交互。
我们可以创建扩展来实现某个特定的功能。例如,可以创建分享扩展(Share Extension),来方便用户把有自己喜欢的网页内容分享到自己的社交账号中去。可以创建 Today widget,用来在通知中心展示用户所关心的新闻内容。还可以创建一个自定义键盘扩展(Custom Keyboard Extension),提供给用户来代替系统的键盘,等等。
值得注意的是我们不能直接在 AppStore 提供一个扩展的下载,扩展一定是随着一个应用一起打包提供的。用户在安装了带有扩展的应用后,可以在设置中来选择开启还是关闭你的扩展。而对于开发者来说,提供扩展的方式是在 app 的项目中加入相应的扩展的 target。扩展一般来说是展现在系统级别的 UI 或者是其他应用中的,Apple 特别指出,扩展应该保持轻巧迅速,并且专注功能单一,在不打扰或者中断用户使用当前应用的前提下完成自己的功能点。因为用户是可以自己选择禁用扩展的,所以要注重用户体验,尽量提供优美流畅的扩展方便用户使用。
App Extension 的种类
iOS和MacOS定义了几种类型的应用程序扩展,每个应用程序扩展都只能展示在系统对应的某个特定的功能区域。例如分享、通知中心和iOS键盘。某个可以启用扩展的系统区域称为扩展点。每个扩展点都定义了使用的规范,并提供了使用该区域的API。我们可以根据应用需要提供的功能来选择对应的扩展。下图是在Xcode8 iOS10系统上的Application Extension。
下面介绍几种常见的扩展:
App Extension | App Extension 简介 |
---|---|
Action (iOS and macOS) | 操作或查看来自主机应用程序的内容。 |
Audio Unit (iOS and macOS) | 生成音频流以发送到主机应用程序,或修改来自主机应用程序的音频流,并将其发送回主机应用程序。 |
Custom Keyboard (iOS) | 自定义键盘替换iOS系统键盘,并能在所有的App中使用。 |
iMessage (iOS) | 与短信应用有关的交互 |
Photo Editing (iOS and macOS) | 可以在系统的照片应用中对图片进行编辑 |
Share (iOS and macOS) | 在别的应用中去发布你想要分享的内容 |
Today (iOS and macOS) | 在“通知中心”的“今日”视图中快速查看内容或执行任务。(Today Extension 也称为 Widget) |
扩展在iOS 10系统中显示的位置:
app extension 与 app 有所区别,extension 必须包含在一个 app 中,每个 extension 是一个独立的二进制文件,运行在 app 中。想要创建一个 extension 必须在某个 app 中添加一个新的 target ,与其他的 target 一样,extension target 有自己的独立配置文件。在一个 app 中可以添加多个 extension target。其中包含 extension 的 app 被称为 containing app。
要想发布你的 extension 供用户使用,必须把 containing app 提交到 App Store。当用户安装你的应用的时候,同时也安装了应用里的 extension。用户安装应用之后,想要使用 extension 必须手动打开,是之处于可用的状态,例如,想要使用应用中的 Today Extension,在通知中心中编辑 Widget ,添加 widget 在通知中心今日视图中才会显示。
App Extension 运行原理
App Extension 不是一个独立的 app ,而是一个在特定的功能区域显示的,实现了使用范围广泛的,特定的功能。
App Extension 生命周期
App Extension不是应用,所以它的生命周期和生存环境和应用相比有很大的区别。在大多情况下是在某个应用的弹出的 activity view controller 中选中了某个extension选项,从而启动了 extension。能够提供给用户去启动 extension 的应用被称为 host app。host app 定义了扩展的上下文,在响应用户操作发送请求时启动扩展生命周期,extension 通常在完成了从 host app 中接收到的请求后终止。如下图所示:
- 用户选择了某个 extension
- 系统实例化定义在 host app 的请求中的 extension,并在extension 和 host app 之间建立联系。extension 在 host app 的上下文中显示其视图,然后使用其在 host app 中接收到的项目来执行任务。
- extension 开始运行,用户可以选择执行或者取消任务,并将其关闭。响应此操作,extension 通过立即执行用户的任务或者必要时启动后台进程来执行 host app 的请求。host app 会撤去 extension的视图,用户会返回到 host app 的之前的上下文中。
- extension 执行过它的任务之后,系统终止 extension。
App Extension 的通信
extension 主要是与它的 host app 来进行通信:host app 发出请求,然后 extension 进行相应。
extension 与它的 containing app 之间没有直接的通信,它们两者之间是两个独立的进程,在 extension 运行的过程中,containing app 可能都没有运行。
extension 的 containing app 和 host app 之间没有通信。
在请求相应的通信过程中,系统从 host app 中打开 extension,在host app提供的扩展上下文中传送数据。extension 展示用户页面,执行一些工作,如果有需要,extension可能会将反馈的数据返回给 host app。
extension 与 containing app 之间可以通过 NSExtensionContext 类的 openURL:completionHandler: 方法来间接地进行通信。extension 和它的containing app 可以访问私有定义的共享容器中的共享数据。
如下图所示:
注意事项
- extension 不同于 app,有些功能不能使用:
- 不能使用
sharedApplication
对象,及对象包含的一写方法。 - 不能使用头文件中标记的任何API与
NS_EXTENSION_UNAVAILABLE
宏或类似的不可用性宏或不可用框架中的任何API
例如,在iOS 8.0中,HealthKit框架和EventKit UI框架不可用于应用程序扩展。 - 不能在后台执行耗时的任务。
- 不能使用 AirDrop 来接收数据。
extension 方便、快捷、高效
开发者应该给用户提供方便快捷高效的extension,在设计你的extension的时候启动一定要迅速,最好启动的时间在1秒以内。如果extension启动太慢,系统可能会终止你的extension。
extension 可使用的内存范围远远低于 app 的,在内存紧张的情况下,系统可能会强行终止 extension,因为用户希望回到 app 中,extension只是辅助性的功能。
所以 extension 应响应迅速、高效运行、占用内存尽可能的少,提供良好的用户体验,这样才能体现 extension的价值。流畅简洁的UI设计
大多数的 extension 需要提供一些用户界面,extension的UI设计应该简洁,并且专注于促进完成单个功能,避免包含不支持扩展的主要任务的无关UI。
用户通过图标和名称来辨别你的extension,所以你的extension的图标已改和对应的containing app的图标一致,这样用户才知道这个扩展是属于哪个应用的。
extension的名称应该是简短、方便识别的,一般情况下的命名规范是:<Containing app name>—<App extension name>,这样可以方便用户来管理整个系统的扩展。确保你的extension适用于所有的设备
必须确保你提交的应用 extension 是通用的,必须适用于 iPhone、iPod Touch、iPad。 Xcode中的应用程序扩展模板需要正确配置为通用目标设备系列。