I'm developing a graphical editor in Swift and Cocoa. I need to save and load information about objects in document.
Objects are represented by a 'Node' class and its descendants. They all implement 'Codable' protocol to make it easier to perform serialization. Therefore I need a way to instantiate an object of a proper Node's descendant during deserialization with Decoder.
I use static method 'from' which returns an instance of a Node's descendant according to its NodeType.
However, this leads to lost of boilerplate code in 'from' method.
Are there any ways of instantiating a proper descendant of a class with Codable?
import Cocoa
enum NodeType: Codable {
case root
case text
case lineBreak
}
class Node: Codable {
let type: NodeType
let id: UUID
enum CodingKeys: CodingKey {
case type
case id
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.type = try container.decode(NodeType.self, forKey: .type)
self.id = try container.decode(UUID.self, forKey: .id)
}
func encode(to encoder: Encoder) throws {
var contrainer = encoder.container(keyedBy: CodingKeys.self)
try contrainer.encode(self.type, forKey: .type)
try contrainer.encode(self.id, forKey: .id)
}
static func from(_ decoder: Decoder) throws -> Node {
let container = try decoder.container(keyedBy: CodingKeys.self)
let type = try container.decode(NodeType.self, forKey: .type)
switch type {
case .root:
return try RootNode(from: decoder)
case .text:
return try TextNode(from: decoder)
case .lineBreak:
return try LineBreakNode(from: decoder)
}
}
}