我正在嘗試構建一個可重用組件,其中包含一個 SwiftUI Picker,它可以在我的應用程式的多個位置使用不同型別。我創建了一個符合 Hashable 的 Pickable 協議,但是當我嘗試使用它時,Picker 和 ForEach 抱怨 Type 'any Pickable' cannot conform to 'Hashable'
import SwiftUI
struct PickerRow: View {
let title: String
let options: [any Pickable]
@State var selection: any Pickable
var body: some View {
HStack {
Spacer()
Text(title)
.font(.subHeading)
Picker(title, selection: $selection, content: {
ForEach(options, id: \.self) {
Text($0.name)
}
}).pickerStyle(.menu)
}
}
}
protocol Pickable: Hashable {
var name: String { get }
}
有沒有辦法在不指定具體型別的情況下讓這樣的東西作業?
uj5u.com熱心網友回復:
如果你考慮一下,這是有道理的。
如果該代碼有效并且您這樣使用它,您希望發生什么?
struct ContentView: View {
let options = [PickableA(), PickableB()]
@State var selection = PickableC()
var body: some View {
PickerRow(title: "Choose one", options: options, selection: $selection)
}
}
那不可能行得通吧?
你需要的是一種方法來確保有一個約束強制options和selection成為相同的具體型別(Equatable例如,考慮兩者String都Int符合,但你不能比較它們)。
一種可能的解決方案是在您的結構宣告中使用通用約束(還要注意@Binding而不是@State因為我們修改了外部值):
struct PickerRow<Option: Pickable>: View {
let title: String
let options: [Option]
@Binding var selection: Option
var body: some View {
HStack {
Spacer()
Text(title)
.font(.subheadline)
Picker(title, selection: $selection) {
ForEach(options, id: \.self) {
Text($0.name)
}
}.pickerStyle(.menu)
}
}
}
你可以這樣使用:
struct Person: Pickable {
let name: String
}
struct ContentView: View {
let options = [Person(name: "Bob"), Person(name: "Alice")]
@State var selection = Person(name: "Bob")
var body: some View {
PickerRow(title: "Choose one", options: options, selection: $selection)
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/536524.html
