Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Swift中在同一类中实现Hashable和NSCoding_Swift_Nscoding_Nscoder_Hashable - Fatal编程技术网

在Swift中在同一类中实现Hashable和NSCoding

在Swift中在同一类中实现Hashable和NSCoding,swift,nscoding,nscoder,hashable,Swift,Nscoding,Nscoder,Hashable,在同一Swift类(或结构)中采用哈希和NSCoding协议时,我遇到了一个问题。哈希性和编码/解码都是独立工作的。但是,一旦NSCoder恢复了对象,哈希性就会丢失 首先,我必须使它成为一个类而不是一个结构,因为显然NSCoding不能与结构一起工作。因此,我显然需要从NSObject继承(它也恰好是可散列的)。不幸的是,NSObject的这种内置哈希性似乎阻止了我以我想要的方式(我想)使自己的类成为可哈希的 这是我的班级: class TileMapCoords : NSObject, NS

在同一Swift类(或结构)中采用哈希和NSCoding协议时,我遇到了一个问题。哈希性和编码/解码都是独立工作的。但是,一旦NSCoder恢复了对象,哈希性就会丢失

首先,我必须使它成为一个类而不是一个结构,因为显然NSCoding不能与结构一起工作。因此,我显然需要从NSObject继承(它也恰好是可散列的)。不幸的是,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>
如果我创建了一个TileMapCoords对象,该对象的行和列与itemsCollected集中的对象相同,“contains”方法会告诉我

1) 最初是在集合中 2) 一旦集合被NSCoder还原/解码,则不在集合中

奇怪的是,对象在集合中,我已经验证了我的对象和集合中的对象具有相同的散列值,并且根据==运算符和isEqual方法是相等的


我需要帮助解决这个问题,或者考虑另一种方法在同一个类中同时具有hashability和NSCodability(可能不重写NSObject?

要自定义
NSObject
子类中的哈希和相等性,需要重写
hash
属性和
isEqual(:)
方法

不幸的是,Swift only
NSObject.hashValue
属性是可重写的(从Swift 4.1开始),但您决不能重写它。 重写<代码>散列< /代码>,以便基金会拾取正确的散列行为——否则基础将使用从“代码”> NSObjult>代码继承的实现,这是基于对象标识的。这不适用于具有自定义
isEqual(:)
实现的
TileMapCoords


通过
NSCoding
解码的集合首先创建为
NSSet
实例,然后桥接到Swift的
Set
类型<代码> NSSET 是一个基础类,因此它使用Foundation的哈希API——很不幸的是,因为上面的代码> TrimaPoCORDS ,导致了您注意到的奇怪行为。将
hashValue
替换为
hash
将解决此问题。

您能解释一下为什么需要实现NSCoding吗?Codable的全部意义在于,它使对结构进行编码变得容易,并且在任何情况下,如果不能使用Codable,您都不会使用NSCoding。那么为什么不直接使用Codable呢?你的代码对我来说很好,不需要在解码后构建第二个集合。请用一个完全可复制的例子来演示你的问题,更新你的问题。在我对集合进行编码然后解码之前,代码工作正常。然后“contains”方法似乎不再在集合中找到(相同的)对象。如果我能将它与结构一起使用,那就太完美了。我将尝试实现它。正如我所说的,你的代码对我有用。甚至在编码和解码之后。这就是为什么您需要发布一个完整的示例来演示这个问题。张贴一些可以复制粘贴到操场上的东西。
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      
 }