来自Implementing Codable for UIColor的问题
struct WrapperOfNSCoding<Wrapped>: Codable where Wrapped: NSCoding {
var wrapped: Wrapped
init(_ wrapped: Wrapped) { self.wrapped = wrapped }
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let data = try container.decode(Data.self)
guard let object = NSKeyedUnarchiver.unarchiveObject(with: data) else {
throw DecodingError.dataCorruptedError(in: container, debugDescription: "failed to unarchive an object")
}
guard let wrapped = object as? Wrapped else {
throw DecodingError.typeMismatch(Wrapped.self, DecodingError.Context(codingPath: container.codingPath, debugDescription: "unarchived object type was \(type(of: object))"))
}
self.wrapped = wrapped
}
func encode(to encoder: Encoder) throws {
let data = NSKeyedArchiver.archivedData(withRootObject: wrapped)
var container = try encoder.singleValueContainer()
try container.encode(data)
}
}
let colors = [NSColor.red, NSColor.brown]
print(colors)
let w = WrapperOfNSCoding(colors[0])
let jsonData = try! JSONEncoder().encode(w) - fails
let jsonData = try! JSONEncoder().encode(colors.map({ WrapperOfNSCoding($0) })) - succeeds
print(jsonData)
let colors2 = try! JSONDecoder().decode([WrapperOfNSCoding<NSColor>].self, from: jsonData).map({ $0.wrapped })
print(colors2)
错误是在编码器中使用单个值时
let w = WrapperOfNSCoding(colors[0])
let jsonData = try! JSONEncoder().encode(w)
错误是
致命错误:&#39;尝试!&#39;表达式意外地引发了一个错误: Swift.EncodingError.invalidValue(WrapperOfNSCoding#1 ......
这成功了
let w = WrapperOfNSCoding([colors[0]])
let jsonData = try! JSONEncoder().encode(w)
为什么会这样?
答案 0 :(得分:2)
JSONEncoder
在顶级需要有效的JSON上下文,可以是[:]
(字典)或[]
(数组),你可以在里面放置一个像这个例子中的元素{ {1}}。
当您保存任何string
对象时,编译器会将该对象视为字符串。在NSCoding
的情况下,您尝试编码JSONEncoder().encode(w)
对象,该对象充当NSCoding
对象而不是常规string
对象。
在JSON
的情况下,对象创建了一个数组,并且每个元素都有一个字符串,在您的情况下为JSONEncoder().encode([w])
。
另一种方式NSCoding
数据是一个字符串,w
是一个数组,每个索引都有一个字符串,因此[w]
没有给你JSONEncoder
错误并为[w]
提供错误。