Hash table is a data structure in programming world. I just want to skip over the definition or basic concept of hash table here, but jump to the Swift case. Briefly speaking, we should return the same hash value for objects considered to be equal. Under this guarantee, a dictionary would behave robustly and effective.

We have mention in the tip of Equality that the using of == in a NSObject subclass will falls back to -isEqual: method if there being no override for this operator in the subclass. The similar for hash calculation in Swift. There is a protocol named Hashable:

protocol Hashable : Equatable {
    var hashValue: Int { get }
}

This protocol is required if you want to use objects of your type as the keys in Swift Dictionary. Some native Swift types such as Int and String are already hashable. For example, the hashValue of an Int is itself:

let num = 19
print(num.hashValue) // 19

In NSObject there is a -hash method. When we overwrite the -isEqual: method for an NSObject subclass, we often need to rewrite -hash at the same time, to supply a method to return the same hash value when the equality checking returning true. In Swift, NSObject conforms Hashable by default, with returning the result of -hash method. It is the similar situation of the == and -isEqual: method.

For pure Swift types, we need to conform Hashable and follow the == operator to give correct hash algorithm; For those NSObject subclass, we can either implement hashValue in Hashable or overwrite -hash of NSObject, depending on whether it would be used in Objective-C or not.

That means, in Objective-C, the safety of NSDictionary is ensured by developers themselves instead of compilers. However, in Swift, when you use pure Swift types and the native Dictionary with a non-hashable key, it will not compile at all. In this respect, we'd better to use Swift types and Dictionary.