Eu vi esse código em um dos vídeos de Paul Hudson. Acessível somente para membros, mas aqui está o texto correspondente: Desafio de codificação
struct Friend: Hashable, Identifiable, Codable {
let id: UUID
/* ... */
}
Conheço o Hashable como uma alternativa ao identifiable, quando você quer usar o objeto com uma lista/ForEach e o objeto não tem ID e você não quer adicioná-lo.
Qual é o propósito de ter ambos (Hashable e Identifiable)?
Hashable
certamente não é uma "alternativa" deIdentifiable
. Eles são completamente diferentes. Aid
propriedade requerida porIdentifiable
precisa ser de umHashable
tipo, mas isso não significa que tudoIdentifiable
também sejaHashable
. Esses protocolos significam coisas diferentes.Você se adapta para
Identifiable
poder distinguir diferentes instâncias desse tipo.Você concorda para
Hashable
poder comparar se duas instâncias desse tipo são iguais entre si e também para fornecer um valor de hash que pode ser usado comoDictionary
chaves, entre outras coisas."Identidade" é diferente de "igualdade", e uma não implica necessariamente a outra. Se eu tiver dois valores de
Banknote
s, ambos podem ser notas de um dólar (igualdade), mas ainda são duas notas de dólar diferentes (identidades diferentes) mesmo assim. Se eu tiver umFriend
, mas eles depois mudarem de nome, eles não seriam os mesmos que seu eu passado (desigualdade), mas ainda são o mesmo amigo (identidade).Para colocar isso de forma mais filosófica, "identidade" é como o Navio de Teseu . Quando você substitui partes do navio, ele claramente se torna diferente (desigual), mas ainda é o mesmo navio? Isso é perguntar se o navio mantém sua "identidade".
Então, conformar-se a ambos
Hashable
eIdentifiable
apenas significa que valores desse tipo podem ser comparados entre si para igualdade, e também há uma maneira de diferenciar entre instâncias. Para alguns tipos, igualdade pode ser equivalente a ser idêntico (por exemplo, você pode querer que umenum
s simples com um número fixo de casos tenha essa propriedade), mas isso não é verdade em geral.No contexto do SwiftUI, ser
Hashable
/Equatable
significa que durante uma atualização de visualização, o SwiftUI pode comparar suas visualizações e evitar chamar desnecessariamente sua visualizaçãobody
se nada mudou. Algumas APIs comoNavigationLink.init
precisam especificamente de umHashable
valor, presumivelmente porque, como uma implementação, esse valor pode ser armazenado em uma tabela hash ou algo assim.Eu diria que Paul Hudson adicionou
Hashable
como solução alternativa para o erro do compilador ao fazer:Mas em vez disso ele deveria ter feito:
O motivo é que
.navigationDestination
ele deve recuperar o amigo do modelo por meio de seu ID para manter o design de fonte única de verdade que o SwiftUI usa. Ou seja, ele não deve ter uma cópia do amigo no caminho de navegação, o que causaria um possível bug de consistência.