App Extension

Extension概述

众所周知,基于iOS系统的安全性考虑,其应用的数据存储是通过沙盒模式进行的,要实现应用之间的数据共享十分困难,功能共享就更加棘手。在iOS8系统中,apple为我们提供了一个革命性的功能:扩展。我们可以通过扩展来使app间数据甚至功能进行共享。
  App Extension出现后,突破了两个重要的iOS限制,那就是:由Open In系统创建的应用程序之间不必要的数据复制无法替换苹果键盘
  然而,其中有一个最可能的误解需要澄清一下,就是iOS 8 App Extensions不同于Android IndentsArs Technica网站撰稿人Andrew Cunningham这样写道。根据Google的描述:

Intent提供了一种机制,用于不同应用程序代码之间的后期运行时绑定。它主要用来启动Activities,因此可以将它看作是Activities之间的粘合剂。从本质上讲,它是一个无源数据结构,存放要执行动作的抽象描述。

虽然Extension在很多情况下与Intent没有什么不同,但在iOS 8中,App Extension系统的整体设计使得它与Intent有很大的不同。

Extension的生命周期

正如苹果文档中的描述,Extension是通过“包含应用程序(containing app)”提供的专门的二进制文件。包含应用程序只负责提供Extension,后者是独立运行的。尽管如此,一个iOS包含应用程序实际上还需要提供Extension之外的某些功能。OS X没有这样的要求,其上的包含应用程序不需要提供任何额外的功能。
虽然说必须有一个「容器软件」来包含各种扩展应用,扩展应用和容器软件仍旧分开运行。每个扩展都是一个以「.appex」作为扩展名的二进制文件。该种类型的文件可以被打开、完成给定任务、而后在容器软件未被关闭的情况下关闭扩展。同时我们也可以预想到,许多的应用软件内有着同样的扩展。比如说,Instagram 的扩展是可以给图像添加滤镜。很多其他的图像处理软件也需要给图像添加滤镜。此时苹果公司鼓励开发者使用「嵌入框架」(embedded framework)共享他们完成此任务的代码。创建嵌入框架的步骤很简单,仅需创建一个框架、把代码放进框架内、而后将框架嵌入容器软件和应用扩展即可。唯一需要注意的地方是这种特性必须在 iOS 8.0 或者后续的系统中才能存在。之前版本的操作系统不支持此种类型的操作。

苹果公司严格的强制回收内存机制是导致需要扩展和容器应用分开运行的重要原因之一。由于用户经常同时开启多个小插件,因此小插件的内存管理受到的限制尤其严格。这从 iPhone 4s 或者 iPad 2 这样的设备上这些内存受限的小插件的运行机制就能看出。
文档提到,Extension的生命周期与它的包含应用程序完全没有关系,它由4个阶段组成:

  • 用户选择一个App Extension
  • 系统启动它
  • App Extension运行
  • 系统终止App Extension


    app_extensions_lifecycle_2x.png

    如果两个应用程序需要同样的Extension做相同的工作,那么这会发生在两个独立的Extension进程中。
    这一方法的主要动机是,通过生命周期短暂的Extension减少内存使用和能量消耗,并防止一个Extension的错误影响到使用了相同Extension的应用程序。

Extension的类型

Extension有多种类型,每一种类型都绑定到一个称为“扩展点(Extension point)”的系统区域:

Extension point Typical app extension functionality
Today (iOS and OS X) Get a quick update or perform a quick task in the Today view of Notification Center(A Today extension is called a widget)
Share (iOS and OS X) Post to a sharing website or share content with others
Action (iOS and OS X; UI and non-UI variants) Manipulate or view content originating in a host app
Photo Editing (iOS) Edit a photo or video within the Photos app
Finder Sync (OS X) Present information about file sync state directly in Finder.
Document Provider (iOS; UI and non-UI variants) Provide access to and manage a repository of files.
Custom Keyboard (iOS) Replace the iOS system keyboard with a custom keyboard for use in all apps
Watch App (iOS) Provide an app, a glance, or a notification UI for Apple Watch, as described in App Programming Guide for watchOS.
  • “今日(Today,又称为Widget)”:可以快速获取更新或者在通知中心的今日视图中执行一项快速任务。
  • 共享:发布到一个共享网站或者与其它应用程序共享内容。
  • 动作:在另一个应用程序的上下文中操作或查看内容。
  • 照片编辑(仅限于iOS):在照片应用程序中编辑照片或视频。
  • 查找器(仅限于OS X):在查找器中直接显示文件同步的状态信息。
  • 文档提供程序(仅限于iOS):提供对文件库的访问和管理。
  • 自定义键盘(仅限于iOS):用自定义键盘替代iOS系统键盘,并用于所有的应用程序中。
  • Watch App(仅限于iOS):为Apple Watch提供一个app,一个glance页面或者一个通知UI,详见: App Programming Guide for watchOS

由于每个扩展点都有与之相关的使用策略和专门的API,开发人员必须为他们想要提供的那种功能选择恰当的扩展点。例如,在默认情况下,键盘Extension“不能访问网络,而且不能与其包含应用程序共享同一容器”。通过对Extension进行恰当的配置,这样的限制可以移除,但开发人员仍然需要遵守苹果应用商店审查指南和iOS开发者计划许可协议中的具体的网络键盘指南。

Extension运行机制

即使是iOS 8 允许运行扩展,却仍旧在应用、应用扩展以及应用数据之间设置了许多的障碍。而这一切正是出于保护用户以及用户隐私的目的。实际上应用之间仍旧不能直接交流。像之前提到的一样,应用扩展是小的二进制文件,并且和容器应用程序分开来运行。调用这些扩展的应用程序(苹果称之为「主应用」,host app)在调用并启动扩展之后会与扩展进行直接的交流,然而主应用与容器应用之间永远不会建立连接。即使主应用想要调用一个扩展,也是通过向苹果的系统框架发送请求。此时仅仅启动应用扩展,而不直接启动容器应用。


simple_communication_2x.png

应用扩展和「主应用」之间可以交流,然而此时扩展和其容器应用之间并不会直接建立联系。
在 FortyTwo 公司的 iOS 开发者 Eduardo Fonseca 向我们解释了 iOS 是如何实现让应用和扩展之间不建立联系的效果的。
「每一个扩展是在主应用程序之内的独立的程序。这些扩展拥有独立的可执行代码。」Fonseca 说,「然而有趣的是实际上扩展并不是应用程序。苹果的系统框架会通过已经事先定义好的接口调用这些扩展。扩展的代码会被分开来单独执行,也就是说第三方应用的『应用空间』内什么都不会执行。这样的话支持使用扩展的应用(比如 Safari)就不会有任何危险。同样,在其他应用内执行你的扩展也不会遇到任何问题。它们就像油和水一样,是完全不会融合的分开的两个部分。」
即使应用程序扩展与其容器应用之间必须有所交流,他们也必须通过系统接口非直接地进行交流。默认下容器应用与其应用程序扩展之间是不可以互相接触到对方的数据的。


detailed_communication_2x.png

扩展和其容器应用必须通过接口和其他用来分享数据的特殊容器进行非直接的交流
为了在容器应用和其应用扩展之间分享数据,你也许需要把容器应用和扩展都设置成一个「应用群」(App Group) 的一部分。这样就可以通过包含应用沙箱和扩展沙箱的一个第三方容器传输二者之间的数据。你可能想过为什么在 iOS 上登录 Chrome 浏览器会让你同时登录谷歌地图或者谷歌云端硬盘。这就是因为 Chrome、谷歌地图和谷歌云端硬盘都是谷歌的应用群的一部分。然而即使在应用群里,数据的分享也有一些限制。它们之间能够分享数据库、缓存信息、登录信息等等,但是本地存储的媒体文件或者其他文件却绝对不能分享。
app_extensions_container_restrictions_2x.png

把容器应用和应用扩展放到一个应用群里能够使它们在分享区域分享一些数据。否则容器应用和应用扩展的数据会被存储在不同的地方。
简单地来总结一下上述内容:苹果公司不想让一个应用能够进入另一个应用的沙箱内。而应用扩展就像是在沙箱里的小沙箱,因此在主应用调用扩展时,扩展不会将容器应用内的数据泄露给主应用。
应用程序扩展的执行方式和应用程序的执行方式也不一样。如果你在不同的应用内同时开起了多个同样的应用程序扩展,系统实际上会打开多个应用程序扩展进程、每个都作为一个独立的进程单独运行。比如说你在 Safari 里打开了一个扩展、而后在邮件里也打开了一个同样的扩展,那么即使扩展都一样,系统实际上会运行两个不同扩展程序进程。这些进程之间不会利用你相同的存储地址区域,因此这能让两个主应用使用独立的数据,并且如果一个应用扩展进程崩溃了也不会影响另一个进程。像 Chrome 和 Safari 这样的浏览器也出于同样的目的,每个网页标签实际上也是分别运行的。

Extension限制

上线限制

像所有未越狱的 iPhone 里的软件一样,所有的 iOS 扩展将需要从苹果应用商城中下载。不过此处最大的限制是苹果公司不会允许开发者提供仅仅作为扩展出现的应用。开发者必须提供一个基本的「容器应用程序」,扩展则作为锦上添花的内容存在于这个基本的应用程序内。苹果公司强调,这个基本的「容器应用」必须提供给用户一些基本的功能,否则他们不会授权该软件登陆应用商店。这一点有别于安卓。

通信限制

对于Extension与其它应用程序之间的通信,苹果有几项强制规定:

1. 调用Extension的应用程序即主应用程序不能启动Extension;只有系统可以启动Extension。
2. 当Extension启动后,主应用程序就和它直接通信。
3. 主应用程序永远不和包含应用程序直接通信。
4. Extension不是一个应用程序,但它由系统生成,并有它自己单独的进程。
5. 为了在包含应用程序和它的Extension之间共享数据,包含应用程序及其Extension都必须是应用程序组的一部分。对于应用程序组的其中两个成员,部分数据可以在两者沙箱之外的第三个容器中共享。

正如Ars Technica的Andrew Cunningham总结的那样,这些
规则的最终结果主要是一个应用程序不能进入另一个应用程序的沙箱。这与Android相反,在Android上,内容提供程序解析程序仍然可以一起工作来为应用程序提供对其它应用程序中数据的访问。

参考链接:

App Extension Programming Guide
App Extension编程指南(iOS8/OS X v10.10):创建应用扩展
WWDC2014 IOS8 APP Extensions
App Extension编程指南(iOS8/OS X v10.10):扩展类型--自定义键盘
如何在Swift中创建Action扩展

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容

  • 从 iOS 8 开始,苹果引入了全新的 App Extension,涉及到方方面面,例如今日面板、键盘、内容拦截器...
    Cyandev阅读 15,300评论 29 85
  • 最近在做一个记事类的App,其中有一个想实现的功能就是希望能够在通知中心查看自己的一些记事内容。正好也是之前写了一...
    水哥阅读 8,234评论 8 56
  • 虾的个头很大,泡在浓稠的酸甜酱汁里面,配着柠檬片和香葱。 吃虾基本靠手,筷子都不用。 抓住虾头和虾尾,轻轻拧一下,...
    记忆半岛阅读 353评论 0 1
  • 北方的夜里, 挂着一轮南方的月, 若不是城市早已睡去, 我或许还不信夜空无星, 可恨的冬日, 清洗如我一般活在梦里...
    光洋阅读 204评论 2 3
  • 小时候的我们很擅长掌握自己的人生。 想当班长,课上多回答两个问题,与老师频繁互动,下课安安静静,本本分分差不多就行...
    晗Hevin阅读 142评论 0 0