Ответ
Чтобы тип мог быть ключом в Dictionary, он должен соответствовать протоколу Hashable. Для структуры это означает:
- Реализовать
Hashable: Протокол требует реализации методаhash(into:), который объединяет хэши всех значимых для равенства свойств. - Реализовать
Equatable: ПосколькуHashableнаследуется отEquatable, необходимо определить оператор==для сравнения двух экземпляров.
Пример ручной реализации:
struct Coordinate: Hashable {
let latitude: Double
let longitude: Double
// 1. Реализация hash(into:)
func hash(into hasher: inout Hasher) {
hasher.combine(latitude)
hasher.combine(longitude)
}
// 2. Реализация Equatable
static func == (lhs: Coordinate, rhs: Coordinate) -> Bool {
return lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude
}
}
// Использование в качестве ключа
var cache: [Coordinate: String] = [:
cache[Coordinate(latitude: 55.75, longitude: 37.61)] = "Москва"
Важно: Swift поддерживает автоматический синтез соответствия протоколам Hashable и Equatable, если все свойства структуры также им соответствуют. В этом случае явно реализовывать методы не нужно.
Ответ 18+ 🔞
Э, слушай, смотри, вот тебе на пальцах, как этот ваш Dictionary работает с ключами. Чтобы твою структуру можно было запихнуть в ключи, ей нужно быть, как это говорят, Hashable. А это, блядь, значит две вещи, запоминай:
- Хэшировать себя уметь: Надо реализовать метод
hash(into:). Туда ты засовываешь все свои значимые свойства, чтобы хэш был уникальный, как отпечаток пальца, ну почти. - Сравнивать себя уметь: Ага, а ещё
Hashable— это сынEquatable. Так что оператор==для сравнения двух твоих структур тоже нужен. Иначе как словарь поймёт, что ключ-то тот же самый?
Вот смотри, как это вручную делается, если ты такой умный и хочешь всё контролировать:
struct Coordinate: Hashable {
let latitude: Double
let longitude: Double
// 1. Вот этот метод, где мы всё комбинируем
func hash(into hasher: inout Hasher) {
hasher.combine(latitude)
hasher.combine(longitude)
}
// 2. А вот сравнение, чтоб было понятно, что две точки — это одна и та же хуйня
static func == (lhs: Coordinate, rhs: Coordinate) -> Bool {
return lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude
}
}
// И теперь можно юзать, ебать его в сраку
var cache: [Coordinate: String] = [:]
cache[Coordinate(latitude: 55.75, longitude: 37.61)] = "Москва"
Но есть же и хорошие новости, ёпта! Swift — он не совсем тупой. Если все свойства твоей структуры сами по себе Hashable (а Double, String, Int — они такие), то можно просто написать : Hashable и нихуя не делать! Компилятор сам всё сгенерит, как шарманка. Это называется автоматический синтез, и он — наше всё. Главное, не выёбывайся зря.