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
,因为 NSKeyedArchiver
和 NSKeyedUnarchiver
不支持元组。
根据"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
和 运行 中删除数据的行以重置存储的数据。
原版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
,因为 NSKeyedArchiver
和 NSKeyedUnarchiver
不支持元组。
根据"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
和 运行 中删除数据的行以重置存储的数据。