【发布时间】:2017-11-29 22:58:40
【问题描述】:
我有一个基类Action,它是一个Operation。它有一堆粗鲁的Operation 东西(KVO 和所有这些)。基类本身实际上不需要编码/解码任何东西。
class Action : Operation, Codable {
var _executing = false
...
}
我有一堆Action 子类,比如DropboxUploadAction,它们直接用他们定义的Input 结构实例化:
let actionInput = DropboxUploadAction.Input.init(...)
ActionManager.shared.run(DropboxUploadAction.init(actionInput, data: binaryData), completionBlock: nil)
子类如下所示:
class DropboxUploadAction : Action {
struct Input : Codable {
var guid: String
var eventName: String
var fileURL: URL?
var filenameOnDropbox: String
var share: Bool
}
struct Output : Codable {
var sharedFileLink: String?
var dropboxPath: String?
}
var input: Input
var output: Output
...
required init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
input = try values.decode(Input.self, forKey: .input)
output = try values.decode(Output.self, forKey: .output)
let superDecoder = try values.superDecoder()
try super.init(from: superDecoder)
}
fileprivate enum CodingKeys: String, CodingKey {
case input
case output
}
override func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(input, forKey: .input)
try container.encode(output, forKey: .output)
try super.encode(to: container.superEncoder())
}
}
当某些情况发生时,例如互联网连接丢失,这些类需要序列化到磁盘以供以后使用。没关系,因为当时我有对它们的引用并且可以用JSONEncoder().encode(action) 对它们进行编码,没问题。
但后来当我想反序列化它们时,我需要指定类的类型,我不知道它是什么。我有一些数据,我知道它可以解码为继承自Action 的类,但我不知道它是哪个子类。我不愿意在文件名中对其进行编码。有没有办法将其解码为基类Action,然后在Action的decode()方法中,以某种方式检测到正确的类并重定向?
过去我使用NSKeyedUnarchiver.setClass() 来处理这个问题。但我不知道如何使用 Swift 4 的 Codable 来做到这一点,而且我知道 NSCoding 现在已弃用,所以我不应该再使用 NSKeyedUnarchiver...
如果有帮助:我有一个 struct Types : OptionSet, Codable,每个子类都会返回它,所以我不必使用类的名称作为其标识。
感谢您的帮助!
【问题讨论】:
-
这是一种可行的方法,但我不喜欢它,因为它很难看:gist.github.com/xaphod/3fda8e584dd840e3a3564da8a5b25846
标签: swift inheritance swift4 codable