【问题标题】:Sharing UserDefaults between extensions在扩展之间共享 UserDefaults
【发布时间】:2018-01-18 08:38:33
【问题描述】:

创建一个 Today 小部件,我正在使用 UserDefaults(suiteName:) 来保存一些数据。在主应用程序中,我使用UserDefaults.standard()。扩展无法读取(或者可以吗?)这就是我使用 suiteName: 构造函数的原因。

用户在主应用程序中坚持到UserDefaults.standard() 的数据需要在扩展程序中可用。

此时我坚持两者,以便可以共享值

 UserDefaults.standard().set:...forKey:...
 UserDefaults(suiteName:...)().set:...forKey:...
 ...

问题是我是否应该将UserDefaults.standard() 全部删除而只在我的应用程序中使用UserDefaults(suiteName:),或者这是一种不好的做法,如果是,为什么?

编辑:我正在使用应用程序组容器。为了澄清,我问我是否应该在整个项目中将standard() 替换为suiteName:

【问题讨论】:

  • 如果你想在扩展和应用之间共享资源,最好的方法是创建一个App Group并使用共享的UserDefault-suiteName:)或仅默认的FileManager-forSecurityApplicationGroupIdentifier:)——您可能不再需要标准的用户默认值或文件管理器(但如果您需要确定要从扩展中隔离数据,您仍然可以使用这些沙盒)。

标签: swift ios-app-extension today-extension userdefaults ios-app-group


【解决方案1】:

您不能使用UserDefaults.standard 在主机应用程序及其应用程序扩展之间共享数据。相反,您必须使用UserDefaults(suiteName:) 创建一个共享容器来共享数据。

即使应用扩展包嵌套在其包含 应用程序的捆绑包,正在运行的应用程序扩展和包含的应用程序没有 直接访问彼此的容器。

要启用数据共享,请使用 Xcode 或开发者门户启用 包含应用程序及其包含的应用程序扩展的应用程序组。 接下来,在门户中注册应用组并指定应用组 在包含的应用程序中使用。

启用应用组后,应用扩展及其包含的应用 都可以使用 NSUserDefaults API 来共享对用户的访问权限 优先。要启用此共享,请使用 initWithSuiteName: 方法 实例化一个新的 NSUserDefaults 对象,传入标识符 共享组的。

更多请参考:https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW1

如何使用应用组:https://github.com/pgpt10/Today-Widget

标准名称还是套件名称?

对仅适用于 Host App 的数据使用标准数据。对要在 Extension 和 Host App 之间共享的数据使用 suiteName。只是不要在它们中保留相同的数据。避免数据冗余。根据上下文使用它们。

【讨论】:

  • 道歉我认为当我使用“initSuiteName:”时,它已经给人一种我在使用应用程序组的印象。我是谁。更新了 OQ 以澄清这一点。谢谢
  • 那么您面临的问题是什么?
  • 我目前正在将相同的数据保存到标准和套件名称构造函数中。我应该放弃standard() 并使用suiteName。
  • 对仅适用于 Host App 的数据使用标准的一种。对要在 Extension 和 Host App 之间共享的数据使用 suiteName。只是不要在它们中保留相同的数据。避免数据冗余。根据上下文使用它们。
【解决方案2】:

确保在功能标签中为您的所有目标(您的应用和扩展程序目标)启用App Groups

然后在创建UserDefaults时使用上面的组标识符作为套件名称:

let userDefaults = UserDefaults(suiteName: "group.com.YourCompany.YourApp")

【讨论】:

  • 这一步非常重要。
  • 我们可以在群组标识符中添加任何名称吗?
【解决方案3】:

我创建共享包的简单示例:

if let userDefaults = UserDefaults(suiteName: "group.your.bundle.here") {
    userDefaults.set("test 1" as AnyObject, forKey: "key1")
    userDefaults.set("test 2" as AnyObject, forKey: "key2")
    userDefaults.synchronize()
}

这是您以后可以阅读的方式:

if let userDefaults = UserDefaults(suiteName: "group.your.bundle.here") {
    let value1 = userDefaults.string(forKey: "key1")
    let value2 = userDefaults.string(forKey: "key2")
    ...
}

【讨论】:

  • 您无需致电synchroniz
  • 这实际上并没有回答使用哪一个的问题。如果数据是使用 UserDefaults.standard() 从主机应用程序保存的,那么如果您执行所写的操作将无法正常工作。
  • 谢谢。它有帮助。我喜欢有代码支持的回答。
【解决方案4】:

还要确保将应用组添加到正确的配置(调试、发布)。如果您在 Debug 中为您的应用程序目标添加 App Groups 并尝试在 Release 配置中为您的扩展使用它,那么它将无法正常工作。

如果你在调试配置中添加(用于应用程序目标),那么在调试配置中使用它(用于扩展目标)

【讨论】:

  • 这太简单了,我浪费了一个小时。感谢您指出这一点
  • 嗯,我希望我在浪费 3 个小时之前阅读了这篇文章......我的扩展组只在个人资料上......
【解决方案5】:

PGDev:增强:

将设置(首选项)https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/UserDefaults/Preferences/Preferences.html 拖到扩展程序时,您无法避免冗余: 它们包含在应用程序私有包中,并且必须被复制 进入套件命名的捆绑包以可供应用扩展使用

【讨论】:

    猜你喜欢
    • 2018-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    相关资源
    最近更新 更多