I want to decode a dictionary with different values. So while the key will always be of type String, the value will have the same superclass (like Shape) but might be composed out of different subclasses (like Rectangle, Circle). I want to be able to later check which subclass is attached, but so far I can only use the default decoding into [ AttachedObject: Shape ].
See the example:
enum AttachedObject: String, Codable {
case chair
case lamp
case desk
}
class Shape: Codable {
var name: String
init(name: String) {
self.name = name
}
}
class Rectangle: Shape {
var width: Double
var height: Double
init(name: String, width: Double, height: Double) {
self.width = width
self.height = height
super.init(name: name)
}
enum CodingKeys: String, CodingKey {
case width
case height
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.height, forKey: .height)
}
required public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.width = try values.decode(Double.self, forKey: .width)
self.height = try values.decode(Double.self, forKey: .height)
try super.init(from: decoder)
}
}
class Circle: Shape {
var radius: Double
init(name: String, radius: Double) {
self.radius = radius
super.init(name: name)
}
enum CodingKeys: String, CodingKey {
case radius
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.radius, forKey: .radius)
}
required public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.radius = try values.decode(Double.self, forKey: .radius)
try super.init(from: decoder)
}
}
class MyRoom: Codable {
public var attachedShapes: [ AttachedObject: Shape ]
enum CodingKeys: String, CodingKey {
case attachedShapes
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.attachedShapes, forKey: .attachedShapes)
}
required public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
fatalError("// How to handle the decoding part?")
}
}