我在尝试在同一个 Swift 类(或结构)中采用 Hashable 和 NSCoding 协议时遇到问题。哈希性和编码/解码都独立工作。然而,一旦一个对象被 NSCoder 恢复,散列性就会丢失。
首先,我必须将其设为类而不是结构,因为显然 NSCoding 不适用于结构。因此,我显然需要从 NSObject 继承(它也恰好是 Hashable)。不幸的是,NSObject 的这种内置散列性似乎阻止了我以我想要的方式使我自己的类可散列(我认为。)
这是我的课:
class TileMapCoords : NSObject, NSCoding {
var row: Int
var column: Int
init(row: Int, column: Int) {
self.row = row
self.column = column
}
// Hashable
override var hashValue: Int {
return column*numTMRows + row
}
static func == (lhs: TileMapCoords, rhs: TileMapCoords) -> Bool {
return
lhs.row == rhs.row &&
lhs.column == rhs.column
}
// do I even need this?
override func isEqual(_ object: Any?) -> Bool {
if let otherCoords = object as? TileMapCoords {
return self == otherCoords
} else {
return false
}
}
// NSCoding
required init?(coder aDecoder: NSCoder) {
row = aDecoder.decodeInteger(forKey: "TileMapCoords.row")
column = aDecoder.decodeInteger(forKey: "TileMapCoords.column")
}
func encode(with aCoder: NSCoder) {
aCoder.encode(row, forKey: "TileMapCoords.row")
aCoder.encode(column, forKey: "TileMapCoords.column")
}
}
我正在创建一组这些对象并对它们进行编码/解码,如下所示:
编码:
aCoder.encode(itemsCollected, forKey: "GameData.itemsCollected")
解码:
var itemsCollected = Set<TileMapCoords>()
itemsCollected = aDecoder.decodeObject(forKey: "GameData.itemsCollected") as! Set<TileMapCoords>
但后来我发现集合中的对象在解码时的哈希值与编码时的哈希值不同。所以我做了一个我认为有效的解决方法:
let itemsCollectedCopy = aDecoder.decodeObject(forKey: "GameData.itemsCollected") as! Set<TileMapCoords>
var itemsCollected = Set<TileMapCoords>()
for coords in itemsCollectedCopy {
itemsCollected.insert(coords) }
当我将它们打印出来时,这个“技巧”似乎纠正了散列值,但是对象仍然没有被正确散列(原因未知)。即当我这样做时:
if curGameData!.itemsCollected.contains(location) {
// do something
}
如果我创建一个 TileMapCoords 对象,该对象与 itemsCollected 集中的对象具有相同的行和列,则“包含”方法会告诉我
1) 最初在集合中 2) 一旦集合已被 NSCoder 恢复/解码,则不在集合中
奇怪的是对象在集合中,我已经验证我的对象和集合中的对象都具有相同的哈希值,并且根据 == 运算符和 isEqual 方法相等。
我需要帮助解决这个问题或考虑另一种方法在同一个类中同时具有哈希性和 NSCodability(也许不覆盖 NSObject?)