示例:
import Foundation
class Player: Codable {
let name: String
init(name: String) {
self.name = name
}
}
class Team: Codable {
let players: [Player]
let capitan: Player
init(players: [Player], capitan: Player) {
self.players = players
self.capitan = capitan
}
}
let player1 = Player(name: "p1")
let player2 = Player(name: "p2")
let team = Team(players: [player1, player2], capitan: player1)
print(team.players[0] === team.capitan) // true
let encoder = JSONEncoder()
let data = try encoder.encode(team)
let decoder = JSONDecoder()
let team2 = try decoder.decode(Team.self, from: data)
print(team2.players[0] === team2.capitan) // false
输出:
true
false
如何将Codable协议与引用类型一起使用?
将来可能会改变这种行为? https://github.com/apple/swift-evolution/blob/master/proposals/0167-swift-encoders.md
答案 0 :(得分:7)
这是JSON的基础,而不是Codable。 JSON是值的编码。它没有跟踪参考;它不是格式的一部分。如果要跟踪引用,则必须通过编码objectIdentifier
自行将其存储在JSON中。然后,您需要加入具有相同标识符的内容。但这超出了Codable的范围,因为基础格式没有这个概念。您需要创建一些其他格式(可能使用JSON作为其基础值格式,方式是NSKeyedArchiver
使用属性列表作为其基础值格式。)
JSON不是对象图存储格式;正如我所说,它是一种价值编码。如果你想要一个对象图,那就是NSKeyedArchiver
的用途。如果您需要非Cocoa解决方案,则需要实现与归档程序实现相同基本思想的新Encoder
和Decoder
。这不是JSONEncoder
的用途。但如果可能,我会使用NSKeyedArchiver
;它专为此而设计。
请注意,SE-0167表示encodeCodable
上有一个新的NSKeyedArchiver
方法,可以让您将Codable
类型与NSCoding
类型混合(并允许Swift)参与NSKeyedArchiver
)的类型,但我在Xcode 9 beta 1中看不到它。
答案 1 :(得分:1)
似乎编码器当前不尊重引用,而是在每次引用时保存同一对象的单独实例,这就是===
失败的原因。您可以将其更改为==
并为您的类实施Equatable
,以解决此问题,或者对问题状态的评论使用结构。