skip to Main Content

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


  1. 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

    Login or Signup to reply.
  2. I think the compiler error you saw leaves the problem a bit unclear. In the question you stated that any Hashable is a type-erased Hashable. However, the signature of the NavigationLink init uses a generic and requires the value to be a very specific type instance that is Hashable. That means the type of itemToLinkTo has to be known at compile time to be passed into the init and any 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

    struct AwesomeNavigationLink<Link: Hashable>: View {
        var itemToLinkTo: Link
        var label: String
        
        var body: some View {
            NavigationLink(value: itemToLinkTo) {
                Text(label)
            }
        }
    }
    

    That moves the type problem upwards. At some point it must be clear and hence explicitly defined of what type itemToLink is though.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search