AppExtension:扩展的学习笔记

一、概述

“扩展”的原理网上有很多,官网也清晰讲明,具体参见以下官方链接。
本文旨在整理笔记,简述相关原理,以备后续查看。

二、AppExtension基本原理

1、搞清楚几个

概念

  • App Extension,Apple定义为”扩展“,也可以理解为”插件“。

  • Host App,能够调起extension的app被称为host app。
    An app that a user employs to choose an app extension is called a host app.
    例如,widget的host app就是Today。

  • Containing App,包含一个或者多个的Extension的App叫做ContainingApp,也叫做宿主App。
    an app that contains one or more extensions is called a containing app

2、iOS是如何处理扩展?

  • 扩展不是独立App,系统将其初始化为单独的进程。
    基于安全和性能的考虑,每一个扩展运行在一个单独的进程中,它拥有自己的bundlebundle后缀名是.appex

    iOS系统把扩展定义为 额外功能的触发入口点,它不是一个独立的App。因此,它必须依赖于宿主App,不能单独存在,也就没办法单独提审AppStore。
    An app extension is not an app. It implements a specific, well scoped task that adheres to the policies defined by a particular extension point.
    An app extension is different from an app. Although you must use an app to contain and deliver your extensions, each extension is a separate binary that runs independent of the app used to deliver it.

3、扩展的生命周期问题(App Extension’s Life Cycle)。

app_extensions_lifecycle_2x.png

主要有以下四个步骤:
1、用户触发“扩展”,如UI触发或者代码触发。
2、iOS系统自动唤起“扩展”。
3、执行“扩展”代码。
4、执行完成后,系统杀死“扩展”,回收资源。

三、扩展相关的通信

1、通信归类

  • Host App 与 ContainingApp 无法直接通信!
    An app extension’s containing app and the host app don’t communicate at all.

  • 扩展与Host App的通信是基于request/response模型。

    simple_communication_2x.png

  • 一般,扩展与ContainingApp是无法直接通信的,例如扩展允许的时候,宿主App可能还未运行。
    There is no direct communication between an app extension and its containing app; typically, the containing app isn’t even running while a contained extension is running.

2、扩展与ContainingApp的有限通信

the limited interaction available between an app extension and its containing app.

  • A Today widget 可以通过UrlSchemes的方式唤起ContainingApp。
    通过NSExtensionContext的方法openURL:completionHandler:

  • 扩展和ContainingApp可以通过shared container实现间接通信。
    数据共享 shared container 与 扩展AppExtension 、ContainingApp的实现彼此双向数据通信。

    detailed_communication_2x.png

3、request/response模型的理解

request/response是通过 ”上下文“ 机制实现。HostApp为”扩展“提供运行的上下文(an extension context)。大致流程是,HostApp将 RequestData 通过上下文(an extension context) 输送给 扩展AppExtension,扩展进行处理(UI显示,用户交互,代码处理等),处理完成后将 ResponseData 返回给HostApp。

由于”扩展“是一个独立的进程,一般一个App也是一个独立进程,因此它们间通信应该是基于进程间的通信方式。例如Socket、管道等,至于哪一种官方好像未说明(待研究)。

4、扩展(App Extension)与宿主App(Containing App)的数据共享shared container

虽然AppExtension的Bundle被导入如ContainingApp的包内,但是彼此的沙盒是没办法访问的。Apple发明了share container的中间层,来实现彼此的数据共享问题。也被称之为AppGroup的概念。
这也映射软件工程的一句经典话语:多了个中间层,一切都显得那么美好。

基本原理如下:Apple允许 App进程扩展进程 都可以对SharedContainer的共享数据区进行操作。

app_extensions_container_restrictions_2x.png

如何集成AppGroup能力?
  • ContainingApp和Extension的Target中,分别都打开AppGroup的能力。
    To enable data sharing, use Xcode or the Developer portal to enable app groups for the containing app and its contained app extensions.

  • 对应的开发和发布证书都必须勾选开启AppGroup的能力。

  • 同一个ContainingApp或者扩展下面,可以有多个AppGroup,根据名字区分,名字必须以group.开头。

  • 开启AppGroup后,App和扩展工程目录下的环境文件.entitlements里面多了一个App Groups

    FE61DC22-9CCC-416D-925A-55AEA2E9083D.png

支持的系统框架
  • NSUserDefaults
    必须使用initWithSuiteName:方法来初始化一个NSUserDefaults对象,其中的SuiteName就是创建的Group的名字,然后利用这个对象来实现,跨应用的数据读写

  • NSFileManager
    通过调用 containerURLForSecurityApplicationGroupIdentifier: 方法可以获得AppGroup的共享目录,然后在此目录的基础上实现任意的文件操作。

  • CoreData
    在初始化CoreData时,先使用NSFileManager取得共享目录,然后再指定共享目录为存储数据文件的目录。

共享数据的数据同步问题!

可以使用CoreData、SQList或者Posix locks锁技术,来实现数据同步问题。
Use Core Data, SQLite, or Posix locks to help coordinate data access in a shared container.

四、代码能力相关

1、能力限制

  • 包含NS_EXTENSION_UNAVAILABLE宏声明的API,则此API在”扩展“中将不可用。
    例如,扩展中无法使用+ (UIApplication *)sharedApplication
  • 不能使用 sharedApplication 对象及其其中的方法。
  • ”扩展“无法使用摄像头和麦克风。
  • ”扩展“无法通过AirDrop接收数据。
  • ”扩展“无法运行长时间的后台任务long-running background tasks
  • 系统严格限制 "扩展" 的内存
    这是因为在同一时间可能会有多个扩展同时运行,如Widget扩展。

2、代码复用

  • 内嵌一个framework文件在扩展和containing app之间共享代码。
    假设你希望在你的containing app与扩展之间共享图片处理的代码,此时你可以将代码打包成framework文件,内嵌到两个目标中。对于内嵌框架中的代码,确保不包含扩展不允许使用的API。
    官方自定义方案-Handling Common Scenarios
扩展Framework的要求
  • 设置扩展Target的Require Only App-Extension-Safe API为YES,否则Xcode会提醒linking against dylib not safe for use in application extensions
    To configure an app extension target to use an embedded framework, set the target’s “Require Only App-Extension-Safe API” build setting to Yes.If you don’t, Xcode reminds you to do so by displaying the warning “linking against dylib not safe for use in application extensions”.

  • 提审必须是包含arm64 (iOS) or x86_64 (OS X)
    A containing app that links to an embedded framework must include the arm64 (iOS) or x86_64 (OS X) architecture build setting or it will be rejected by the App Store.

  • 勾选Copy Files build phase.
    When configuring your Xcode project, you must choose “Frameworks” as the destination for your embedded framework in the Copy Files build phase.

五、实例

见另外一篇推送支持图片,详见:
AppExtension:NotificationServiceExtension集成、调试、打包的实践


参考

官网-Adding an App to an App Group.
官网-App Extensions Increase Your Impact
iOS 8新特性之扩展
App Extension编程指南(iOS8/OS X v10.10)中文版
iOS扩展开发攻略(一) - Share Extension
活久见的重构 - iOS 10 UserNotifications 框架解析

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

推荐阅读更多精彩内容