通过应用程序组在应用程序之间传递和保持数据
iOS 8昨天透露了一个关于应用程序组的新API。 之前分享数据和应用程序之间的通信是一种混乱,我相信这正是应用程序组旨在纠正的。
在我的应用程序中,我启用了应用程序组,并添加了一个新的组,但是我找不到任何有关如何使用它的文档。 文档和API参考仅说明如何添加组。
那么应用程序组真正打算做什么? 是否有任何文件的地方如何使用它?
应用程序组的另一个好处是可以共享一个NSUserDefaults
数据库。 这也适用于扩展(通知中心小部件,自定义键盘等)。
在应用程序组的所有应用程序中像这样初始化你的NSUserDefaults
对象,它们将共享数据库:
Objective-C的:
[[NSUserDefaults alloc] initWithSuiteName:@"<group identifier>"];
迅速:
NSUserDefaults(suiteName: "<group identifier>")
请记住,每个应用程序的[NSUserDefaults standardUserDefaults]
数据库中的所有内容都不会传递到此数据库中。
文档也给出了一个正确的例子(从Beta 3开始)。
并且不要忘记同步数据库:
[yourDefaults synchronize];
在多个应用程序之间共享NSUserDefaults数据
为了在应用程序和扩展程序之间或两个应用程序之间共享默认值,您必须使用以下步骤在设置中添加应用程序组:
- 在Project Navigator中点击* .xcodeproj文件(应该在顶部)。
- 在项目导航器的右侧查找项目和目标。 在目标下点击你的主要目标(应该是目标下的第一个目标)。
- 朝上方,点击能力标签。
- 在“应用程序组”部分中,单击右侧的开关将“应用程序组”打开。
- 点击+button,添加一个名为group.com.company.myApp的应用程序组。
- 转到其他应用程序中的相同位置,现在可以select此组。 为每个将使用此共享数据的应用启用此组。
注意:如果您转到Apple Developer Portal(显示所有证书,标识符,设备和configuration文件的Apple网站)并转到标识符>应用程序组,您应该看到这个新的应用程序组。
存储数据:
var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp") userDefaults!.setObject("user12345", forKey: "userId") userDefaults!.synchronize()
要检索数据:
var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp") if let testUserId = userDefaults?.objectForKey("userId") as? String { print("User Id: \(testUserId)") }
根据我对现有文档的解释,应用程序组主要针对扩展,更具体地说,针对小部件。 小部件是他们自己的应用程序包,与您的应用程序共存。 由于它们是独立的应用程序,因此拥有自己的沙箱,因此您需要使用应用程序组来共享文件。
在一些标题grep'ing后,我想我find了所需的API,但实际上是作为iOS 7的一部分。
NSFileManager
在其上有一个方法containerURLForSecurityApplicationGroupIdentifier:
在开启应用程序的App Groups时,你可以在其中传入你创build的标识符:
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.company.app"];
我今天采用的一个重要陷阱如下:
在许多项目中,我看到了一个应用程序目标,并为该目标的每个configuration设置了不同的包标识符。 这里事情变得混乱。 开发人员的目的是为debuggingconfiguration创builddebugging应用程序,并为发布目标创build一个生产应用程序。
如果你这样做,两个应用程序将分享相同的NSUserDefaults,如此设置
var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp") userDefaults!.setObject("user12345", forKey: "userId") userDefaults!.synchronize()
这在许多地方引起问题:
- 想象一下,当一个特殊的app-intro屏幕已经显示给用户时,你为一个按键设置了YES。 另一个应用程序现在也读取YES,不显示介绍。
- 是的,某些应用程序还会将oAuth令牌存储在其用户默认值中。 无论如何…根据实施,应用程序将认识到有一个令牌,并开始使用错误的令牌检索数据。 机会很高,这将失败,奇怪的错误。
一般来说,解决这个问题的方法是在默认键的前面加上当前的configuration。 您可以在运行时通过为您的configuration设置不同的包标识符来轻松检测到configuration。 然后,只需从NSBundle.mainBundle()
读取包标识符。 如果你有相同的包标识符,你需要设置不同的预处理器macros
#ifdef DEBUG NSString* configuration = @"debug"; #elif RELEASE NSString* configuration = @"release"; #endif
在Swift中,它看起来几乎是一样的:
#if DEBUG let configuration = "debug" #elseif RELEASE let configuration = "release" #endif
储藏
let shared: NSUserDefaults = NSUserDefaults(suiteName: "group.abcapp")! shared.setObject("abc.png", forKey: "favEmoji") shared.synchronize()