Swift 中 class 的 encoding/decoding 非平凡 属性 的方法

Approach to encoding/decoding nontrivial property of a class in Swift

原版Post

我有一个 class 正在使用 NSCoding 进行编码和解码。我了解了如何对数字或字符串等基本类型进行编码,我什至链接了符合 NSCoding 的 classes。我还了解了如何对这些基本类型的数组进行编码。

我现在遇到的问题是对字符串、数组和对的组合进行编码。具体来说,我正在尝试编码这样定义的 属性

var configuration: [([String], String)]

此配置中某些条目的示例 属性 可以这样可视化:

configuration[0] = (["config1", "config2"], "2 configuration options")
configuration[1] = (["config1", "config2", "config3"], "3 configuration options")

所以我的问题是如何将其编码为一对。我正在考虑将这对阵列拆分为 2 个平行阵列。然后我将它们编码为 [[String]](我想我知道该怎么做)和 [String]。我只是用 2 个单独的字符串键对它们进行编码,例如 "configuration0""configuration1"(对于 .0.1 部分)。然后我可以从这些字符串键中解码它们并将它们重新配对在一起。

有没有更好的方法encode/decode?

编辑(对 zaph 回答的回应):

我尝试使用 vanilla encodeObject 对其进行编码。这是代码:

var configuration: [([String], String)] = Array<([String], String)>(count: 2, repeatedValue: ([],""))
var firstConfig: ([String], String) = (["config1", "config2"], "2 configuration options")
var secondConfig: ([String], String) = (["config1", "config2", "config3"], "3 configuration options")
configuration[0] = firstConfig
configuration[1] = secondConfig
coder.encodeObject(configuration, forKey: "configuration")

我得到的错误是:Cannot invoke 'encodeObject' with an argument list of type '([([String], String)], forKey: String)'

如果包含的所有对象都是 NSCoding 兼容对象,则只需将 encodeObject 用于 configuration

configuration是一个包含字符串数组和字符串的数组应该没有问题。

除了 Zaph 的回答和评论中的信息外,我还将自己的解决方案作为独立答案提交。

因为 configuration 是一个元组数组,您将无法使用 encodeObject,因为 NSKeyedArchiverNSKeyedUnarchiver 不支持元组。

根据"The Swift Programming Language" footnote on tuples:

Tuples are useful for temporary groups of related values. They are not suited to the creation of complex data structures. If your data structure is likely to persist beyond a temporary scope, model it as a class or structure, rather than as a tuple. For more information, see Classes and Structures.

元组可以表示为具有 2 个属性的 class:一个用于第一部分,一个用于第二部分。虽然使它成为 class 并符合 NSObject 和 NSCoding 的额外样板很多,但它使对象在将来使用时更加灵活,因此它有其权衡。

我创建 a Gist 是为了通过示例项目展示它的实际效果。只需用此文件和 运行(在文件顶部定义的 class 对象)替换新的单视图应用程序项目的 ViewController.swift

第一次 运行 viewDidLoad 上没有存储数据,将创建示例数据并将其存储在 viewDidAppear 上。 运行 再次显示,您会看到 viewDidLoad 存储的数据已正确加载。您可以再次取消注释从 NSUserDefaults 和 运行 中删除数据的行以重置存储的数据。