I’m a bit confused by an error I’m seeing in the new Xcode beta around the new any
syntax in Swift.
I have a view that takes an any Hashable
, and I’m trying to pass that to a parameter that takes a Hashable
parameter. However, I get this error from Xcode: Type 'any Hashable' cannot conform to 'Hashable'
. I can’t see why this should be, as I thought an any Hashable
is essentially a type-erased Hashable, right?
Here’s a full code sample to illustrate what I’m trying:
struct AwesomeNavigationLink: View {
var itemToLinkTo: any Hashable
var label: String
var body: some View {
NavigationLink(value: itemToLinkTo) {
Text(label)
}
}
}
This causes the above error on the NavigationLink line.
My questions are: Should I be able to pass a any Hashable
to a Hashable
? If so, how, or is this a bug? If not, why? Thanks in advance!
2
Answers
Maybe this Answer by @technerd help
Hashable contains self where AnyHashable not
Having Self in a protocol is kind of like a protocol with a generic parameter, and the generic parameter is always the conforming class. This causes the protocols to be unable to be used on its own like Set because the "generic parameter" is unknown. AnyHashable solves this problem by not using Self at all so it now becomes a normal struct. It "erases" the generic Self type.
you can read the full comment here Difference between Any, Hashable, AnyHashable
I think the compiler error you saw leaves the problem a bit unclear. In the question you stated that
any Hashable
is a type-erasedHashable
. However, the signature of theNavigationLink
init
uses a generic and requires thevalue
to be a very specific type instance that isHashable
. That means the type ofitemToLinkTo
has to be known at compile time to be passed into the init andany Hashable
is literally anything that can be hashed which is not enough for the compiler.A solution could be to make your view generic too with
That moves the type problem upwards. At some point it must be clear and hence explicitly defined of what type
itemToLink
is though.