我有一个基类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
,然后在decode()
的{{1}}方法中,以某种方式检测正确的类并重定向?
过去我曾使用Action
来处理此问题。但是我不知道如何使用Swift 4 NSKeyedUnarchiver.setClass()
来做到这一点,我知道NSCoding现在已被弃用,所以我不应该再使用Codable
了......
如果有帮助:我有一个NSKeyedUnarchiver
每个子类返回,所以我不必使用该类的名称作为其身份。
感谢您的帮助!
答案 0 :(得分:1)
嗯NSCoding
并未弃用。我们仍然在通过init(coder:)
从故事板中实例化UIViewControllers时使用它。
此外,如果您仍然不想使用NSCoding
,则可以将Input
,Output
和Types
存储到结构中并序列化改为磁盘。
struct SerializedAction {
let input: Input
let output: Output
let type: Type
}
如果需要,您可以对其进行解码,并通过Action
属性决定使用输入/输出初始化正确的type
。
class DropboxAction: Action {
...
init(input: Input, output: Output) {
...
}
}
您不一定需要对整个Action
对象进行编码。