【发布时间】:2018-07-22 22:45:54
【问题描述】:
我在尝试在同一个 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 集中的对象相同,'contains' 方法会告诉我
1) 最初在集合中 2) 一旦集合被 NSCoder 恢复/解码,就不在集合中
奇怪的是对象 IS 在集合中,我已经验证了我的对象和集合中的对象都具有相同的哈希值,并且根据 == 运算符和 isEqual 方法相等。
我需要帮助解决这个问题或考虑另一种方法来在同一个类中同时具有哈希性和 NSCodability(也许不覆盖 NSObject?)
【问题讨论】:
-
你能解释一下为什么你需要实现 NSCoding 吗? Codable 的全部意义在于它可以轻松地对结构进行编码,并且在任何情况下都不会使用 NSCoding 而不能使用 Codable。那么为什么不直接使用 Codable 呢?
-
您的代码对我来说工作得很好,无需在解码后构建第二组。请使用完全可重现的示例来说明您的问题,更新您的问题。
-
代码工作正常,直到我对集合进行编码然后对其进行解码。然后“包含”方法似乎不再在集合中找到(相同的)对象。
-
好吧,老实说我不知道 Codable。如果我可以将它与结构一起使用,那将是完美的。我会努力实现的。
-
正如我所说,您的代码对我有用。即使在编码和解码之后。这就是为什么您需要发布一个完整的工作示例来演示该问题。将可以按原样复制和粘贴的内容发布到 Playground 中。
标签: swift nscoding nscoder hashable