Dictionary key requires Hashable
conformance:
class Test {}
var dictionary = [Test: String]() // Type 'Test' dies not conform to protocol 'Hashable'
class Test: NSObject {}
var dictionary = [Test: String]() // Works
How to get address of pure Swift class instance to use as hashValue
?
For Swift 3 (Xcode 8 beta 6 or later), use 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
}
Then a == b
iff a
and b
refer to the same instance of the class (
and a.hashValue == b.hashValue
is satisfied in that case).
Example:
var dictionary = [Test: String]()
let a = Test()
let b = Test()
dictionary[a] = "A"
print(dictionary[a]) // Optional("A")
print(dictionary[b]) // nil
For Swift 2.3 and earlier, you could use
/// 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>
to implement a hash value, and the identity operator ===
to
implement the Equatable
protocol.
Swift 3
This based on the great code snippet in Martin R's answer with insightful comment from 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
If you don't want or cannot implement Hashable
for some reason it's easy to use an Objective C helper:
(long )getPtr:(SomeType* )ptr { return (long )ptr; }
long
maps to Swift Int
and can be perfectly used as a Swift Dictionary
key on both 32 and 64bit architectures. It was the fastest solution which I found while profiling different approaches, including unsafeAddress
. In my case performance was the main criteria.