macOS 命令行应用程序 - 用户默认值 dictionaryRepresentation 显示太多值

macOS command line app - User Defaults dictionaryRepresentation shows too many values

我正在 Xcode 中开发一个 macOS 命令行应用程序,它使用用户默认值。我的用户默认值有以下代码

if let configDefaults = UserDefaults.init(suiteName: "com.tests.configuration") {
    configDefaults.set("myStringValue", forKey: "stringKey")
    configDefaults.synchronize()
    print(configDefaults.dictionaryRepresentation())
}

这将在 ~/Library/Preferences 文件夹中创建我自己的 .plist 文件。如果我查看该文件,我只能看到我添加的单个值,这非常好。但是当我在我的 UserDefaults 对象上调用 dictionaryRepresentation() 时,还有很多其他属性(我猜来自共享的 UserDefaults 对象),比如

com.apple.trackpad.twoFingerFromRightEdgeSwipeGestureAKLastEmailListRequestDateKey

查看 UserDefaults 的文档,这似乎与 UserDefaults 的搜索列表有关,并且 standard 对象在搜索列表中:

func dictionaryRepresentation() -> [String : Any]

Returns a dictionary that contains a union of all key-value pairs in the domains in the search list.

还有用于 UserDefaults 对象的方法 addSuiteremoveSuite,所以我猜我需要从我的 configDefaults 对象中删除 .standard 套件,但我不知道名字,应该在方法中使用它。

是否可以从字典表示中删除 .standard 默认值?我基本上只是想把我自己的所有数据都放在字典里,仅此而已。

我试图只从 UserDefaults 获取我的值的原因是,有许多自定义类型的对象 Connection(存储连接到服务器的配置),它们是保存在 UserDefaults 中。在程序启动时,我希望能够将所有对象加载到我的应用程序中。因此我认为我可以使用 dictionaryRepresentation(),因为它会 return UserDefaults 中的所有元素。但是字典中应该只有我的 Connection 个对象,这样我就可以将它转换为 [String: Connection].

鉴于您的目的(在您对问题的最新编辑中),您应该做的是将 Connection 对象的集合存储在一个键下。然后,查找该密钥以获取集合。

不清楚集合应该是 Connection 个对象的数组还是一个将字符串映射到 Connection 的字典。这是你可以做出的选择。

但是,在任何情况下,您都不应该依赖于默认值是空的。

换句话说,你会做:

UserDefaults.standard.set(yourStringToConnectionDictionary, forKey:"yourSingleKey")

及以后:

let connectionMap = UserDefaults.dictionary(forKey:"yourSingleKey")

然后通过 name/ID/whatever 在 connectionMap 中查找 Connection

尽管从设计的角度来看,Ken Thomases 提出的其他解决方案可能更好,但我找到了一个完全符合我最初要求的解决方案。打电话

UserDefaults.standard.persistentDomain(forName: "com.company.TestApp.configuration")

Returns 一个字典,仅包含我添加到域 com.company.TestApp.configuration 的值,使用

let configs = UserDefaults.init(suiteName: "com.company.TestApp.configuration")!
configs.set(someData, forKey: someKey)

奇怪的是在 Apple 文档中关于 persistentDomain(forName:):

Calling this method is equivalent to initializing a user defaults object with init(suiteName:) passing domainName and calling the dictionaryRepresentation() method on it.

但事实并非如此(见我的问题)。非常欢迎对此主题进行澄清。