Swift: Hashable.hashValue устарел как требование протокола;

У меня возникла следующая проблема (это просто предупреждение) с моим проектом iOS.

Hashable.hashValue устарел как требование протокола; согласовать тип ActiveType с Hashable, реализовав вместо этого hash (into :)

  • Xcode 10.2
  • Swift 5

Исходный код:

public enum ActiveType {
    case mention
    case hashtag
    case url
    case custom(pattern: String)

    var pattern: String {
        switch self {
        case .mention: return RegexParser.mentionPattern
        case .hashtag: return RegexParser.hashtagPattern
        case .url: return RegexParser.urlPattern
        case .custom(let regex): return regex
        }
    }
}

extension ActiveType: Hashable, Equatable {
    public var hashValue: Int {
        switch self {
        case .mention: return -1
        case .hashtag: return -2
        case .url: return -3
        case .custom(let regex): return regex.hashValue
        }
    }
}

введите описание изображения здесь

Есть лучшее решение? Само предупреждение предлагает мне реализовать хэш (в :), но я не знаю, как?

Ссылка: ActiveLabel


person Krunal    schedule 28.03.2019    source источник
comment
см. здесь: hashable -улучшения   -  person Anbu.Karthik    schedule 28.03.2019
comment
Почему вы вообще перезаписываете hashValue? Компилятор может автоматически синтезировать Hashable соответствие для вашего enum. Вам также не нужно явно указывать Equatable соответствие, поскольку Hashable наследуется от Equatable, поэтому, когда вы объявляете Hashable соответствие, Equatable методы синтезируются для вас.   -  person Dávid Pásztor    schedule 28.03.2019
comment
Предыстория: Hashable отошел от того, чтобы просить соответствующие типы о hashValue: Int, описывающем самих себя, к тому, чтобы просить их принять Hasher и смешать себя с ним (путем смешивания в своих полях). Раньше люди испытывали трудности с получением хороших хеш-значений для объектов с несколькими полями, часто прибегая к хакам, таким как XOR для всех элементов (a ^ b ^ c) или, что еще хуже, взяв строковое значение строки, которая объединяет элементы ("\(a)-\(b)-\(c)".hashValue). Теперь вместо этого вы просто указываете хешеру, что хешировать, и он использует соответствующий алгоритм хеширования, чтобы сделать это от вашего имени.   -  person Alexander    schedule 24.11.2019


Ответы (1)


Как говорится в предупреждении, теперь вы должны реализовать функцию hash(into:).

func hash(into hasher: inout Hasher) {
    switch self {
    case .mention: hasher.combine(-1)
    case .hashtag: hasher.combine(-2)
    case .url: hasher.combine(-3)
    case .custom(let regex): hasher.combine(regex) // assuming regex is a string, that already conforms to hashable
    }
}

Было бы даже лучше (в случае перечислений и структур) удалить пользовательскую реализацию hash(into:) (если вам не нужна конкретная реализация), поскольку компилятор автоматически синтезирует ее для вас.

Просто сделайте свое перечисление соответствующим ему:

public enum ActiveType: Hashable {
    case mention
    case hashtag
    case url
    case custom(pattern: String)

    var pattern: String {
        switch self {
        case .mention: return RegexParser.mentionPattern
        case .hashtag: return RegexParser.hashtagPattern
        case .url: return RegexParser.urlPattern
        case .custom(let regex): return regex
        }
    }
}
person Rico Crescenzio    schedule 28.03.2019
comment
если вы удалите hashable как тип (из расширения / класса), вы также можете избавиться от предупреждения - person itsmcgh; 21.02.2020