iOS 8 中扩展(Extension)和容器应用(Containing App)的之间的数据共享
原文 http://www.itiger.me/?p=181
主题 iOS8
扩展(Extension)是 iOS 8 和 OSX 10.10 中引入新功能,Extension 不会单独存在,它将做为 App 的附加功能出现,为 App 提供更好的交互体验。由此 Extension 和容器应用(Containing App)之间的数据共享在所难免。Apple 在它的 官方文档 中只是以 NSUserDefaults 举例做了介绍,然后丢了一句“ Use Core Data, SQLite, or Posix locks to help coordinate data access in a shared container.”就算完事儿了。下面就来介绍下具体如何操作。
Extension Target
喵神在 WWDC 2014 Session笔记 – iOS 通知中心扩展制作入门 已经有了非常详尽的介绍,总之你需要在项目中添加一个 Application Extension Target( File > New Target > Application Extension > …),然后就可以从你非常熟悉的 view controller 开始编写 widget 代码了。
App Groups
在默认情况下,Extension 是无法直接获取 Containing App 的数据的,但在 iOS 8 中我们可以通过开启 App Groups 以实现同一个 team 的 Apps 及其 Extension 之间的数据共享。开启 App Groups:
在 Xcode 6 的 Targets 中选中主 App‘s Target,找到 Capabilities 标签
找到 App Groups 选项并展开,然后戳一下添加按钮
给你的 App Groups 起个名字,通常是 group.xxx 的格式,随后 Xcode 自动创建 .entitlements 授权文件,其中包含了共享容器的访问名称,并将此 App Group 登记在你的开发者账号下的,确保只有你的 team 的 app 可以使用这些共享容器
选中 Extension’s Target,重复以上操作,勾选刚才创建的 group 就可以了
现在你把原来存在 App 沙箱中的数据改存在 这个 group 中就可以实现数据的共享了,在具体举例之前,你可能发现仅有数据好像还不够,比如你使用了 CoreData,还需要选中 .xcdatamodeld 文件和要用到的 model 文件,在 Xcode 的右侧工具栏中的找到 Target Membership 勾选 Extension 名,把它们加到 Extension Target 中。然后把 .xcdatamodeld 文件加到 Extension 的 Resource Bundle 里面:
Targets 中选中 Extension‘s Target,找到 Build Phase 标签
找到 Copy Bundle Resources 选项并展开,然后戳一下添加按钮
添加相应的 .xcdatamodel 文件
数据共享
好了,一切准备就绪,把
[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
换成
[[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.xxx"]
也就是让主 App 和 Extension 都去访问共享容器中的文件,从而实现数据的共享。现在“you can also use Core Data, or in some cases SQLite, to help coordinate data access in a shared container.”(捂嘴笑)
如果是 NSUserDefaults 就是把
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
换成
NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.xxx"];