关于App Extension

App Extension

 App Extension可以让你扩展你APP的自定义功能和内容,使用户可以在与其他应用或者系统进行互动的时候去使用它。

  • extension并不是一个独立的app,它有一个包含在app bundle中的独立bundle;
  • extension不能单独存在,必须有一个包含它的containing app;
  • 不同的extension激活方式不同;
  • 常见的种类包括Today Widget、Share Extension、Action Extension、Document Provider、Custom Keyboard

containing app

containing app我们可以把它理解为容器App。

尽管苹果开放了extension,但是在iOS中extension并不能单独存在,要想提交到AppStore,必须将extension包含在一个app中提交,并且app的实现部分不能为空,这个包含extension的app就叫containing app。

host app

我们可以把它理解为宿主的App,能够调起extension的app被称为host app。

比如:Safari app 里面网页分享到微信, Safari就是 host app ; widget的host app就是Today。

App Extensions的生命周期

以下是Apple官方提供的图片

  1. 用户选择要使用的App extension

  2. 系统启动App Extension

  3. App Extension 代码运行

  4. 运行完之后系统kill掉App Extension

这就是App Extension的生命周期,举个例子:

一个Share Extension,在图库里面你选择了一张图片,然后点击分享,选择你的Share Extension(第一步),此时系统会启动你的Share Extension(第二步)。然后你将选择的图片分享到指定的程序(例如微信的发送给朋友)(第三步)。接下来分享页面关闭,系统kill掉了Share Extension。

与Host App的通讯

Host app (如微信) ; App extension (safari里面分享点击出来的微信extension);Containing app (safari)

Containing App和app Extension并没有直接的沟通。甚至有的时候Containing app可以不运行,而App Extension直接运行。Containing app和Host app没有任何的沟通。

还有一种是app extension可以直接和他的containing app沟通:

例如Today Widget,可以直接告诉系统打开他的Containing app,只需要调用NSExtensionContext的openURL:CompletionHandler:方法即可。

app extension和containing app可以共同读写一个被称为Shared resources的存储区域,这是通过App Groups实现的。

App Groups 实现数据共享

需要先配置好开发者账号中的 app group id

  • 在app中开启 TARGETS–>ApplictionExtension–>Capabilities–>App Groups
  • 在extension中开启 TARGETS–>BPToday–>Capabilities–>App Groups

通过NSUserDefaults共享数据

写入数据

1
2
3
4
5
//  AppDelegate.m

NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"app group name"];
[userDefaults setObject:@"共享数据" forKey:@"content"];
[userDefaults synchronize];

读取数据

1
2
3
4
//  TodayViewController.m

NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"app group name"];
NSLog(@"%@",[userDefaults objectForKey:@"content"]);

通过NSFileManager共享数据

保存数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- (BOOL)saveTextByNSFileManager { 

NSError *err = nil;
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"app group name"];

containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/good"];

NSString *value = _textField.text;
BOOL result = [value writeToURL:containerURL atomically:YES encoding:NSUTF8StringEncoding error:&err];

if (!result) {

NSLog(@"%@",err);
} else {

NSLog(@"save value:%@ success.",value);
}

return result;

}

读取数据

1
2
3
4
5
6
7
8
9
10
11
12
- (NSString *)readTextByNSFileManager { 

NSError *err = nil;

NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"app group name"];

containerURL = [containerURL URLByAppendingPathComponent:@"Library/Caches/good"];

NSString *value = [NSString stringWithContentsOfURL:containerURL encoding:NSUTF8StringEncoding error:&err];

  return value;
}

代码共享

framework 可以在extension和containing app之间共享代码。

即将framework分别嵌入到extension和containing app的target中实现代码共享。

在App Extension中不可以做的事情

  1. 访问sharedApplication对象。因此不能使用任何该对象的防范;

  2. 使用任何标记NS_EXTENSION_UNAVAILABLE宏的API,或者类似的宏,或者不可用framework里面的API,例如HealthKit framework不能用于app extensions;

  3. iOS设备访问相机或者麦克风(iMessage app可以访问这些资源,只要在Info.plist里面进行配置使用描述即可);

  4. 运行一个长时间的后台任务(根据不同平台而异);

  5. 使用隔空投送接收数据;

Demo传送门