在swift词典中作为关键引用

时间:2015-05-20 09:30:21

标签: swift dictionary key hashtable memory-address

字典键需要Hashable一致性:

class Test {}
var dictionary = [Test: String]() // Type 'Test' dies not conform to protocol 'Hashable'

class Test: NSObject {}
var dictionary = [Test: String]() // Works

如何获取纯粹的Swift类实例的地址以用作hashValue

3 个答案:

答案 0 :(得分:18)

对于Swift 3(Xcode 8 beta 6或更高版本),请使用ObjectIdentifier

class Test : Hashable {
    // Swift 2:
    var hashValue: Int { return unsafeAddressOf(self).hashValue }
    // Swift 3:
    var hashValue: Int { return ObjectIdentifier(self).hashValue }
}

func ==(lhs: Test, rhs: Test) -> Bool {
    return lhs === rhs
}

然后a == b iff ab引用同一个类的实例( 并且a.hashValue == b.hashValue在这种情况下感到满意。)

示例:

var dictionary = [Test: String]()
let a = Test()
let b = Test()
dictionary[a] = "A"
print(dictionary[a]) // Optional("A")
print(dictionary[b]) // nil

对于Swift 2.3及更早版本,您可以使用

/// Return an UnsafePointer to the storage used for `object`.  There's
/// not much you can do with this other than use it to identify the
/// object
func unsafeAddressOf(object: AnyObject) -> UnsafePointer<Void>

实现哈希值,以及身份运算符=== 实施Equatable协议。

答案 1 :(得分:1)

Swift 3

这基于Martin R's answer中的精彩代码段,其中包含来自Christopher Swasey的深刻见解

class Test: Hashable, Equatable {
    lazy var hashValue: Int = ObjectIdentifier(self).hashValue

    static func ==(lhs: Test, rhs: Test) -> Bool {
        return lhs === rhs
    }
}

var dictionary = [Test: String]()
let a = Test()
let b = Test()
dictionary[a] = "A"
print(dictionary[a]) // Optional("A")
print(dictionary[b]) // nil

答案 2 :(得分:0)

如果您因某些原因不想或不能实施Hashable,那么使用Objective C帮手很容易:

(long )getPtr:(SomeType* )ptr { return (long )ptr; }

long映射到Swift Int,可以完美地用作32位和64位架构上的Swift Dictionary密钥。这是我在分析不同方法时发现的最快的解决方案,包括unsafeAddress。在我看来,表现是主要标准。