Как я могу обновить этот Hashable.hashValue, чтобы он соответствовал новым требованиям?

Я пытаюсь исправить старый учебник с сайта RayWenderlich, который больше не поддерживается. Предупреждение появляется в трех файлах, Chain.swift, Cookie.swift и Swap.swift из учебника «Как сделать игру похожей на Candy Crush с SpriteKit и Swift:»

Я в растерянности даже после изучения доступных ответов, которые появляются во многих местах. Я изо всех сил пытаюсь понять, что делает этот код, чтобы я мог это исправить. Я знаю, что это просто предупреждение, и я, вероятно, могу его проигнорировать, но игра также показывает X, где должны появляться пустые плитки, поэтому я подозреваю, что это может иметь какое-то отношение к этому?

Предупреждение следующее:

'Hashable.hashValue' is deprecated as a protocol requirement; conform type 'Chain' to 'Hashable' by implementing 'hash(into:)' instead

Пример файла

  class Chain: Hashable, CustomStringConvertible {
  var cookies: [Cookie] = []
  var score = 0

  enum ChainType: CustomStringConvertible {
    case horizontal
    case vertical

    var description: String {
      switch self {
      case .horizontal: return "Horizontal"
      case .vertical: return "Vertical"
      }
    }
  }

  var chainType: ChainType
  init(chainType: ChainType) {
    self.chainType = chainType
  }

  func add(cookie: Cookie) {
    cookies.append(cookie)
  }

  func firstCookie() -> Cookie {
    return cookies[0]
  }

  func lastCookie() -> Cookie {
    return cookies[cookies.count - 1]
  }

  var length: Int {
    return cookies.count
  }

  var description: String {
    return "type:\(chainType) cookies:\(cookies)"
  }

  var hashValue: Int {
    return cookies.reduce (0) { $0.hashValue ^ $1.hashValue }
  }

  static func ==(lhs: Chain, rhs: Chain) -> Bool {
    return lhs.cookies == rhs.cookies
  }
}

person Harry McGovern    schedule 04.04.2019    source источник
comment
Я видел это. Извините, это не помогло. Документация Apple еще более неясна.   -  person Harry McGovern    schedule 04.04.2019
comment
Предыстория: Hashable отошел от того, чтобы просить соответствующие типы о hashValue: Int, который описывает самих себя, к просьбе принять Hasher и смешать себя с ним (путем смешивания в своих полях). Раньше люди испытывали трудности с получением хороших хеш-значений для объектов с несколькими полями, часто прибегая к хакерским приемам, таким как XOR для всех элементов (a ^ b ^ c) или, что еще хуже, взяв строковое значение строки, которая объединяет элементы ("\(a)-\(b)-\(c)".hashValue). Теперь вместо этого вы просто говорите хешеру, что хешировать, и он использует соответствующий алгоритм хеширования, чтобы сделать это от вашего имени.   -  person Alexander    schedule 24.11.2019


Ответы (1)


Из документации Hashable:

Хеширование значения означает передачу его основных компонентов в хеш-функцию, представленную типом Hasher. Существенными компонентами являются те, которые способствуют реализации Equatable данного типа. Два равных экземпляра должны передавать в Hasher одни и те же значения в хэше (into :) в одном и том же порядке.

И из документации hash(into:):

Компоненты, используемые для хеширования, должны быть такими же, как компоненты, сравниваемые в реализации оператора == вашего типа. Вызовите hasher.combine (_ :) с каждым из этих компонентов.

Реализация

static func ==(lhs: Chain, rhs: Chain) -> Bool {
    return lhs.cookies == rhs.cookies
}

показывает, что cookies является «существенным компонентом», который определяет равенство экземпляров. Следовательно

func hash(into hasher: inout Hasher) {
    hasher.combine(cookies)
}

является допустимой (и разумной) реализацией требования Hashable.

person Martin R    schedule 04.04.2019
comment
Хорошо, если я добавлю этот действительный код, просто добавлю его, ошибка в этом файле исчезнет. Но все равно не работает. конечно. Если я удалю блок с помощью статической функции, как показано, он будет жаловаться на цепочку. Тип «Цепочка» не соответствует протоколу «Equatable» - person Harry McGovern; 04.04.2019
comment
@HarryMcGovern: Почему вы удалили static func ==? - person Martin R; 04.04.2019
comment
Спасибо, похоже, эта часть работает. Мне нужно опубликовать новый вопрос, связанный с этим руководством. - person Harry McGovern; 05.04.2019
comment
хорошо, он снова появится в игре. var value = topLeft.hashValue value = value | topRight.hashValue ‹---------------- 1 значение = значение | bottomLeft.hashValue ‹---------------- 2 value = value | bottomRight.hashValue ‹---------------- 3 - person Harry McGovern; 05.04.2019
comment
@HarryMcGovern: Понятия не имею, о чем вы говорите, в вашем вопросе нигде нет кода. Я бы посоветовал задать новый вопрос (с некоторым автономным кодом, демонстрирующим проблему). - person Martin R; 05.04.2019