gpt4 book ai didi

swift - 在 Swift 4 中使用 Decodable 和继承

转载 作者:行者123 更新时间:2023-11-30 11:15:58 27 4
gpt4 key购买 nike

使用类继承是否会破坏类的可解码性。例如下面的代码

class Server : Codable {
var id : Int?
}

class Development : Server {
var name : String?
var userId : Int?
}

var json = "{\"id\" : 1,\"name\" : \"Large Building Development\"}"
let jsonDecoder = JSONDecoder()
let item = try jsonDecoder.decode(Development.self, from:json.data(using: .utf8)!) as Development

print(item.id ?? "id is nil")
print(item.name ?? "name is nil") here

输出为:

1
name is nil

现在,如果我反转这个,名称会解码,但 id 不会。

class Server {
var id : Int?
}

class Development : Server, Codable {
var name : String?
var userId : Int?
}

var json = "{\"id\" : 1,\"name\" : \"Large Building Development\"}"
let jsonDecoder = JSONDecoder()
let item = try jsonDecoder.decode(Development.self, from:json.data(using: .utf8)!) as Development

print(item.id ?? "id is nil")
print(item.name ?? "name is nil")

输出为:

id is nil
Large Building Development

而且你不能在这两个类中表达 Codable。

最佳答案

我相信在继承的情况下,您必须自己实现编码。也就是说,您必须在父类(super class)和子类中指定 CodingKeys 并实现 init(from:)encode(to:)。根据 WWDC video (49:28左右,如下图),您必须使用 super 编码器/解码器调用 super 。

WWDC 2017 Session 212 Screenshot at 49:28 (Source Code)

required init(from decoder: Decoder) throws {

// Get our container for this subclass' coding keys
let container = try decoder.container(keyedBy: CodingKeys.self)
myVar = try container.decode(MyType.self, forKey: .myVar)
// otherVar = ...

// Get superDecoder for superclass and call super.init(from:) with it
let superDecoder = try container.superDecoder()
try super.init(from: superDecoder)

}

视频似乎没有显示编码端(但它是 encode(to:) 端的 container.superEncoder() ),但它在很多方面都有效在 encode(to:) 实现中采用相同的方式。我可以确认这在这个简单的情况下有效(请参阅下面的 Playground 代码)。

我自己仍然在与一些奇怪的行为作斗争,我正在从 NSCoding 转换一个更复杂的模型,它有很多新嵌套的类型(包括 struct > 和 enum),表现出这种意外的 nil 行为并且“不应该”。请注意,可能存在涉及嵌套类型的边缘情况。

编辑:嵌套类型似乎在我的测试 Playground 中工作得很好;我现在怀疑自引用类(认为树节点的子节点)有问题,其自身的集合也包含该类的各种子类的实例。对简单自引用类的测试可以很好地解码(即没有子类),因此我现在将精力集中在子类案例失败的原因上。

2017 年 6 月 25 日更新:我最终向 Apple 提交了有关此问题的错误。 rdar://32911973 - 不幸的是,包含 Subclass: Superclass 元素的 Superclass 数组的编码/解码循环将导致数组中的所有元素被解码为 父类(super class)(子类的init(from:)永远不会被调用,导致数据丢失或更糟)。

//: Fully-Implemented Inheritance

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 class)和子类属性均在 fullSubDecoded 中恢复。

关于swift - 在 Swift 4 中使用 Decodable 和继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51748266/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com