问题描述
当我解码子类(RegularCard)的数组时,我得到了超类(Card)的数组。编码很好,我测试了一下,编码工作正常。但是,当我解码时,未调用解码子类(RegularCard)的函数。我的代码如下。我在另一则帖子中发现了以下错误:
17年6月25日更新:我最终向苹果提交了一个有关此的错误。 rdar:// 32911973-不幸的是,包含子类的超类数组的编码/解码周期:超类元素将导致该数组中的所有元素都被解码为超类(子类的init(from :)从未被调用,从而导致数据丢失或更糟)。
这是在此post中。
$resultimg = str_replace("data:image/png;base64,","",$base64strImg);
header('Content-Disposition: attachment;filename="test.png"');
header('Content-Type: image/png');
echo base64_decode($resultimg);
'''
解决方法
对我来说很好:
let reg = RegularCard(id: 1,front: "yo",score: 20,back: "frf")
let arr = [reg]
let data = try! JSONEncoder().encode(arr)
let arr2 = try! JSONDecoder().decode([RegularCard].self,from: data)
print(type(of:arr2)) // Array<RegularCard>
let what = arr2.first!
print(what.id,what.front,what.score,what.back) // 1 yo 20 frf
请注意,我确实需要稍微更改您的代码;我将第二个CodingKeys更改为CodingKeys2,因为否则我无法编译您的代码。
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 CodingKeys2 : String,CodingKey {
case back
case id
case front
case score
case cardType
}
override func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys2.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: CodingKeys2.self)
print("decoding regular")
back = try values.decode(String.self,forKey: .back)
try super.init(from: decoder)
}
}
不过,我确实明白你的意思;即使使用RegularCard,如果我们解码为Card,也无法将其恢复为RegularCard的值(不能向下转换)。我猜那只是Codable或泛型的本质。基本上,我的建议是不要这样做。
但是,在这种情况下,您可以尝试将其解码为RegularCard,如果不起作用,则尝试将其解码为Card。这样,您始终可以获得正确的答案。
let card = Card(id: 2,front: "hoo",score: 10,cardType: .regular)
let reg = RegularCard(id: 1,back: "frf")
let arr1 = [card]
let arr2 = [reg]
let data1 = try! JSONEncoder().encode(arr1)
let data2 = try! JSONEncoder().encode(arr2)
// first data1
do {
let result1 = try JSONDecoder().decode([RegularCard].self,from: data1)
print(result1)
} catch {
let result2 = try JSONDecoder().decode([Card].self,from: data1)
print(result2) // it's a Card
}
// now data2
do {
let result1 = try JSONDecoder().decode([RegularCard].self,from: data2)
print(result1) // it's a RegularCard
} catch {
let result2 = try JSONDecoder().decode([Card].self,from: data2)
print(result2)
}