2015-05-20 91 views
10

字典鍵鍵需要Hashable一致性:參考在迅速詞典

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

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

如何獲得純斯威夫特類實例的地址作爲hashValue使用?

回答

15

對於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協議。

+0

'unsafeAddressOf'就是我一直在尋找。謝謝! – Kirsteins

+0

會有'unsafeAddressOf'會爲同一個變量返回一個不同地址的情況嗎?我似乎遇到了這個問題,無法再現它。該地址首先會說一件事,然後它會改變,就好像Swift將變量移動到其他地方的內存中一樣。 – pixelfreak

+0

不適用於* class *的實例。但是,請參閱http://stackoverflow.com/questions/32638879/swift-strings-and-memory-addresses,其中會發生某些*值類型*,它們隱式橋接到某些NSObject的情況。 –

0

如果你不想或者不能出於某種原因很容易使用的目標C幫手實施Hashable

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

long映射到斯威夫特Int和可完美用作斯威夫特Dictionary關鍵在32位和64位體系結構上。這是我在分析不同方法時發現的最快解決方案,其中包括unsafeAddress。在我的情況下,表現是主要標準。

1

斯威夫特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