为什么 Set 不是 属性 列表类型?

Why is Set not a property list type?

我试图在用户默认值中保存一个 Set<String> 类型并得到一个 "Attempt to set a non-property-list object" 错误..

这让我想知道,为什么 Set 不是 属性 列表类型?

为什么允许数组和字典,但不允许集合?

编辑:我知道其他存储数据的方法。我只是想知道 Apple 决定 Set 不是 属性 列表类型是否有已知或估计的原因。

是因为Set没有像Arrays(index)和Dictionaries(key)那样的key吗?是因为 Sets 是无序的吗?但是字典也是无序的..

您需要先存档您的集合,使其成为 Data 对象。只有这样,您才能将该数据存储为默认值。

像这样:

let sets: Set<String> = Set(arrayLiteral: "a","b","c")
let encodedData = NSKeyedArchiver.archivedData(withRootObject: sets)
UserDefaults.standard.setValue(encodedData, forKeyPath: "test")

然后要取消存档您的数据,请这样做(然后您可以取回您的数据集)

if let data = UserDefaults.standard.data(forKey: "test"),
    let set = NSKeyedUnarchiver.unarchiveObject(with: data) as? Set<String> {
    print(set)
}

至于不存档就不能存储你的set的原因,Apple是这样说的:

A default object must be a property list—that is, an instance of (or for collections, a combination of instances of) NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. If you want to store any other type of object, you should typically archive it to create an instance of NSData.

https://developer.apple.com/documentation/foundation/userdefaults

如您所见,如果您将集合转换为 ArrayData,则最好将其存储为 UserDefaults

属性 列表代表数据,而不是实现细节。数组是有序列表。字典是字符串键到值的映射。什么是"set?" 在简单的文本数据中没有什么特别的意思。如果列表不能有重复项,就不要写重复项。如果它是无序的,则忽略该顺序。一切 "set-like" 都与数据操作有关。 (对于实际上 did 具有重复元素的 plist-set,您期望什么行为?它会无效吗?如果不是,它怎么不只是一个数组?)

属性 列表不是通用的对象树序列化工具。这就是 NSCoder 的用途。它们主要是为像 Info.plist 这样的人类可写配置而设计的,并且可以用任何语言进行解析。 NSUserDefaults 也不是通用数据存储(如果是,它会被称为 "NSApplicationDataStore" 或类似的东西)。它旨在以用户可以手动编辑的方式存储用户配置数据。

原始 (NeXTSTEP) 格式更易于输入:

SomeKey = {
    MyFirstProperty = ("here's", "a", "list");
    SomeOtherThing = "I'm a string";
};

Apple 使用 OS X 切换到 XML,这使得打字变得更加困难,但基本方法是相同的。 (在 OS X 的早期,Apple 做了很多动作将 Java 集成到系统中,包括更多地依赖 XML 包括 formal DTDs。回想起来,许多这些举动中的一部分可能是不幸的,但在当时是有道理的。)

Plists 解决了与 JSON 相同的问题。它们提供了对原始数据进行编码所需的一组最小类型,而不是用于实现算法的数据结构。

我并不是说 plist 是根据一些数学第一原理创建的。如果 NSSet 是配置数据中非常常见的类型,我敢肯定它会找到自己的方式进入格式。但它们并不是为了成为保存任意应用程序数据的通用方式而发明的,NSUserDefaults 也不是。