Conformar con Hashable

Cuando un tipo de dato se conforma con Hashable adquiere la capacidad de generar hashes en sus instancias.

struct Item {
    let id: Int
    let name: String
    let url: URL?
}

extension Item: Hashable {
    var hashValue: Int {
        return "\(id)-\(url?.absoluteString ?? "no_url")".hashValue
    }
}

func ==(lhs: Item, rhs: Item) -> Bool {
    return lhs.hashValue == rhs.hashValue
}

let item = Item(id: 9, name: "My Item", url: URL(string: "https://items.org"))

Hashable hereda del protocolo Equatable, por lo que es necesario implementar las funciones de Equatable también.

El valor del hash que se retorne de las instancias que se conforman con Hashable debe de ser representativo de una instancia en particular del mismo tipo de dato.

Si los hashValue de dos instancias del mismo tipo de dato son iguales, se considera que ambas instancias son iguales e intercambiables.

A partir de Swift 4.1

Con la actualización 4.1 de Swift, ya no es necesario crear la implementación de Hashable manualmente, pues ahora el compilador lo hará automáticamente para tipos de datos en los cuales todas sus propiedades almacenadas tengan tipos de datos que se conformen con Hashable.

struct Community: Equatable {
	let name: String
	let id: Int
	let date: Date
	
	// El compilador genera automáticamente hashValue puesto
	// que todas las propiedades son tambíen Hashable.
}

Sin embargo, aún se puede definir el comportamiento que hashValue debe tener manualmente si así se desea, proporcionando una implementación personalizada como en el ejemplo de arriba.