When I decode an array of the subclass(RegularCard), I get an array of the superclass (Card). The encoding is fine, I tested it and the encoding worked fine. But, when I decode, the function to decode the subclass(RegularCard) isn't called. My code is below. I found the error in another post with the following:
Update June 25 '17: I ended up filing a bug with Apple about this. rdar://32911973 - Unfortunately an encode/decode cycle of an array of Superclass that contains Subclass: Superclass elements will result in all elements in the array being decoded as Superclass (the subclass' init(from:) is never called, resulting in data loss or worse).
This was in this post.
class Card : Codable {
var id: Int
var front: String
var score: Int
var cardType : CardType
init(id: Int, front : String, score: Int, cardType : CardType) {
self.id = id
self.front = front
self.score = score
self.cardType = cardType
}
enum CodingKeys : String, CodingKey {
case id
case front
case score
case cardType
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
print("encoding super")
try container.encode(id, forKey: .id)
try container.encode(front, forKey: .front)
try container.encode(score, forKey: .score)
try container.encode(cardType.rawValue, forKey: .cardType)
}
required init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
print("decoding super")
self.id = try values.decode(Int.self, forKey: .id)
self.front = try values.decode(String.self, forKey: .front)
self.score = try values.decode(Int.self, forKey: .score)
self.cardType = CardType(rawValue: try values.decode(String.self, forKey: .cardType))!
}
}
enum CardType : String {
case regular = "regular"
case multipleChoice = "multipleChoice"
case numbered = "numbered"
case bulleted = "bulleted"
case acronym = "acronym"
case image = "image"
}
class RegularCard : Card {
var back: String
init(id: Int, front : String, score: Int, back : String) {
self.back = back
super.init(id: id, front: front, score: score, cardType: .regular)
}
enum CodingKeys : String, CodingKey {
case back
case id
case front
case score
case cardType
}
override func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
print("encoding Regular")
try super.encode(to: encoder)
try container.encode(back, forKey: .back)
}
required init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
print("decoding regular")
back = try values.decode(String.self, forKey: .back)
try super.init(from: decoder)
}
}
'''