我相信在继承的情况下,您必须实现Coding
自己。也就是说,你必须指定CodingKeys
和执行init(from:)
,并encode(to:)
在这两个超和子类。对于WWDC视频(约49:28,如下图所示),您必须使用超级编码器/解码器调用超级。
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
myVar = try container.decode(MyType.self, forKey: .myVar)
let superDecoder = try container.superDecoder()
try super.init(from: superDecoder)
}
该视频似乎没有停止显示编码方面(但是是container.superEncoder()
针对编码方面的encode(to:)
),但是在encode(to:)
实现过程中其工作方式几乎相同。我可以在这种简单的情况下确认这项工作(请参见下面的操场代码)。
我仍在自己的怪异行为中挣扎NSCoding
,它要转换的模型要复杂得多,该模型具有许多新嵌套的类型(包括struct
和enum
),这些类型表现出这种意外的nil
行为,并且“不应该”。请注意,可能存在涉及嵌套类型的边缘情况。
编辑:嵌套类型似乎在我的测试操场上工作正常;我现在怀疑自引用类(认为是树节点的子代)有问题,而自引用类本身也包含该类的各种子类的实例。一个简单的自引用类的测试可以很好地解码(即没有子类),因此我现在将精力集中在子类案例失败的原因上。
更新时间:17年6月25日:我最终向苹果提交了一个有关此问题的错误。rdar:// 32911973-不幸的是Superclass
,包含Subclass: Superclass
元素的数组的编码/解码周期将导致数组中的所有元素被解码为Superclass
(init(from:)
从未调用子类,从而导致数据丢失或更糟)。
class FullSuper: Codable {
var id: UUID?
init() {}
private enum CodingKeys: String, CodingKey { case id }
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(UUID.self, forKey: .id)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
}
}
class FullSub: FullSuper {
var string: String?
private enum CodingKeys: String, CodingKey { case string }
override init() { super.init() }
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let superdecoder = try container.superDecoder()
try super.init(from: superdecoder)
string = try container.decode(String.self, forKey: .string)
}
override func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(string, forKey: .string)
let superencoder = container.superEncoder()
try super.encode(to: superencoder)
}
}
let fullSub = FullSub()
fullSub.id = UUID()
fullSub.string = "FullSub"
let fullEncoder = PropertyListEncoder()
let fullData = try fullEncoder.encode(fullSub)
let fullDecoder = PropertyListDecoder()
let fullSubDecoded: FullSub = try fullDecoder.decode(FullSub.self, from: fullData)
super和subclass属性都在中还原fullSubDecoded
。