使 Swift 存在的“任何”协议符合 Hashable

问题描述 投票:0回答:1

我在使用 新的“存在

any
”更改来使 Swift 5.7+ 中的存在变量保持一致时遇到了一些麻烦。

由于这里的

Animal

总是符合
Hashable
,我想
any Animal
也会
have符合Hashable

但是,我看到的错误让我产生了不同的想法。有人可以帮助解释为什么会发生这种情况吗?如果可能的话,请帮助我解决它?

import SwiftUI import PlaygroundSupport protocol Animal: Hashable { var name: String { get } } struct Cow: Animal { let name: String } struct Chicken: Animal { let name: String } let anAnimalList: [any Animal] = [Cow(name: "Aaron"), Chicken(name: "Billy"), Cow(name: "Charlie"), Chicken(name: "Delilah")] struct myView: View { @State private var anAnimal: (any Animal)? var body: some View { VStack { List(anAnimalList, id: \.self, selection: $anAnimal) { animal in // ERROR: Type 'any Animal' cannot conform to 'Hashable' Text("Animal") } Text("Animal is \(anAnimal?.name ?? "Null")") } } } PlaygroundPage.current.setLiveView(myView())
    
ios swift swiftui swiftui-list
1个回答
3
投票
假设我们想要找到一种方法来列出

[any Animal]

,而不是“为什么会发生这种事”:)(请参阅相应的 WWDC22 会议以找到第二个会议的答案)

使用 Xcode 14b3 / iOS 16 进行测试

我们跳进这个洞吧...

原代码有两个地方报错:

List(anAnimalList, id: \.self, // << 1st place selection: $anAnimal // << 2nd place ) { animal in Text("Animal") }

第一名 - 因为Animal

不可识别,并且
self
涉及具体类型的实例,所以我们不应该使用
\.self
(因为编译器将无法推断具体类型),而是直接通过
进行识别\.id

因此,这是第一个问题的可能解决方案:

protocol Animal: Hashable, Identifiable { var id: UUID { get } var name: String { get } } struct Cow: Animal { let id = UUID() let name: String } struct Chicken: Animal { let id = UUID() let name: String } var body: some View { VStack { List(anAnimalList, id: \.id) { animal in // << no error !! Text("Animal: \(animal.name)") } } }

第二名 - 现在进行选择;故事是一样的,Swift 应该知道“具体的选择类型”或者能够“从代码中推断出来”,这两者在编译类型上都是不可能的,所以不要试图用头打破墙壁,让我们找到一扇门。 .

一个可能的解决方案是使用上下文中已知且具体的东西来进行选择...我们刚刚在上面添加了它 - 'id'

所以这是第二部分的修复

@State private var anAnimalID: UUID? // << here !! var body: some View { VStack { List(anAnimalList, id: \.id, selection: $anAnimalID) { animal in Text("Animal: \(animal.name)") } if let animal = anAnimalList.first { $0.id == anAnimalID } { Text("Animal is \(animal.name)") } } }

在 GitHub 上测试代码

© www.soinside.com 2019 - 2024. All rights reserved.