使用应用程序组在应用程序之间传递和保存数据

str*_*eem 81 objective-c ios ios8 ios-app-extension

iOS 8昨天发布了一个关于App Groups的新API.在分享数据和在应用程序之间进行通信之前,它有点混乱,我相信这正是App Groups要纠正的内容.

在我的应用程序中,我启用了应用程序组并添加了一个新组,但我找不到任何有关如何使用它的文档.文档和API参考仅说明如何添加组.

那么App Group真正打算做什么呢?有没有关于如何使用它的文件?

San*_*aus 79

App Groups的另一个好处是共享NSUserDefaults数据库的能力.这也适用于App Extensions(通知中心小部件,自定义键盘等).

NSUserDefaults在应用程序组的所有应用程序中初始化您的对象,他们将共享数据库:

Objective-C的:

[[NSUserDefaults alloc] initWithSuiteName:@"<group identifier>"];
Run Code Online (Sandbox Code Playgroud)

迅速:

NSUserDefaults(suiteName: "<group identifier>")
Run Code Online (Sandbox Code Playgroud)

请记住[NSUserDefaults standardUserDefaults],每个应用程序的数据库中的所有内容都不会延续到此数据库中.

文档给出了正确的示例以及(作为β3的).

并且不要忘记同步数据库:

[yourDefaults synchronize];
Run Code Online (Sandbox Code Playgroud)

  • 注意:如果您使用iOS 8扩展(例如键盘),则需要确保您的扩展在其Info.plist文件中具有RequestsOpenAccess = YES. (8认同)
  • @MikeRichards不确定,但如果我没记错,应用程序组的前缀是团队ID (3认同)
  • 仅适用于模拟器(XCode 6 beta 5,iOS 8 beta 5) (2认同)

Ten*_*Jay 69

在多个应用程序之间共享NSUserDefaults数据

要在应用和分机之间或2个应用之间共享默认值,您必须使用以下步骤在设置中添加应用组:

  1. 在Project Navigator中,单击*.xcodeproj文件(应位于顶部).
  2. 在Project Navigator的右侧查找Project和Targets.在目标下点击您的主要目标(应该是目标下的第一件事).
  3. 在顶部,单击"功能"选项卡.
  4. 在"应用程序组"部分中,单击右侧的开关以打开"应用程序组".
  5. 单击+按钮,然后添加名为group.com.company.myApp的应用程序组.
  6. 转到其他应用中的相同位置,此组现在可供选择.为将要使用此共享数据的每个应用启用此组.

注意:如果您访问Apple Developer Portal(显示所有证书,标识符,设备和配置文件的Apple网站)并转到标识符>应用程序组,您应该会看到这个新的应用程序组.

存储数据:

var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp")!
userDefaults.setObject("user12345", forKey: "userId")
userDefaults.synchronize()
Run Code Online (Sandbox Code Playgroud)

要检索数据:

var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp")
if let testUserId = userDefaults?.objectForKey("userId") as? String {
  print("User Id: \(testUserId)")
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!花了一些时间搜索文档来弄清楚如何做到这一点,我认为其他人可能会欣赏我采取的步骤。 (2认同)

Way*_*man 36

根据我对现有文档的解释,应用程序组主要针对扩展,更具体地说,针对小部件.窗口小部件是他们自己的应用程序包,与您的应用程序共存.由于它们是单独的应用程序,因此拥有自己的沙箱,因此您需要使用应用程序组来共享文件.

在一些标题grep'ing之后,我认为我找到了所需的API,但实际上是作为iOS 7的一部分放入的.

NSFileManager有一个方法containerURLForSecurityApplicationGroupIdentifier:,您可以传入您为应用程序打开应用程序组时创建的标识符:

NSURL *containerURL = [[NSFileManager defaultManager] 
           containerURLForSecurityApplicationGroupIdentifier:@"group.com.company.app"];
Run Code Online (Sandbox Code Playgroud)


bla*_*acx 5

我今天探讨的一个重要陷阱是:

在许多项目中,我看到了一个应用程序目标,并为该目标的每种配置设置了不同的包标识符。事情变得混乱了。开发人员打算为调试配置创建一个调试应用程序,为发布目标创建一个生产应用程序。

如果这样做,则两个应用程序在设置时将共享相同的NSUserDefaults

var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp")
userDefaults!.setObject("user12345", forKey: "userId")
userDefaults!.synchronize()
Run Code Online (Sandbox Code Playgroud)

这会在许多地方引起问题:

  1. 想象一下,当向用户显示特殊的应用程序简介屏幕时,您将键设置为“是”。现在,另一个应用程序也会显示YES,并且不显示简介。
  2. 是的,某些应用程序还在其用户默认设置中存储了oAuth令牌。无论如何...根据实现的不同,应用程序将识别出存在令牌,并开始使用错误的令牌检索数据。这很可能会因奇怪的错误而失败。

通常,此问题的解决方案是在默认键之前添加当前构建的配置。通过为配置设置不同的捆绑包标识符,可以在运行时轻松检测配置。然后只需从中读取包标识符NSBundle.mainBundle()。如果您具有相同的包标识符,则需要设置不同的预处理器宏,例如

#ifdef DEBUG
  NSString* configuration = @"debug";
#elif RELEASE
  NSString* configuration = @"release";
#endif
Run Code Online (Sandbox Code Playgroud)

在Swift中,外观几乎相同:

#if DEBUG
  let configuration = "debug"
#elseif RELEASE
  let configuration = "release"
#endif
Run Code Online (Sandbox Code Playgroud)

  • 存在问题是因为您将所有数据混合在一个共享的UserDefaults中。您应该将NSUserDefaults.standardUserDefaults()用于不应共享的数据。 (8认同)

yoA*_*ex5 5

iOS 应用组

App Group允许您在同一开发团队(帐户)的不同进程(应用程序、扩展...)之间共享数据(UserDefaults、文件、CoreData(管理模型图)、POSIX 锁)。它创建一个应该从保存/缓存数据开始的shared container文件,您可以访问思想 URL 和 IPCidgroup.

App Group与 UserDefaults 一起使用

  1. 为所有目标(应用程序、扩展程序...)添加App Group具有相同 ID 的功能,您将从中获得访问权限 在此输入图像描述

创建完成后您可以在Apple Developer上查看。证书、ID 和配置文件 -> 标识符 -> 所有组

在此输入图像描述

  1. 从应用程序1写入
let defaults = UserDefaults(suiteName: "group.goforit")
defaults?.setValue("Hello World!", forKey: "key1")
Run Code Online (Sandbox Code Playgroud)
  1. 从应用程序2读取
let defaults = UserDefaults(suiteName: "group.goforit")
let result = defaults?.value(forKey: "key1") //Hello World!
Run Code Online (Sandbox Code Playgroud)

shared container根位置单个 URL。

let rootURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.goforit")

//file:///Users/alex/Library/Developer/CoreSimulator/Devices/1AF41817-FE2E-485A-A592-12C39C0B0141/data/Containers/Shared/AppGroup/DC14D43F-2C2C-4771-83BE-64A9F54BD2E1/
Run Code Online (Sandbox Code Playgroud)

[iOS 应用扩展]