Why can't I select items from this picker view? The difference here is my selection array consist two different Structs('CustomOptionOne' and 'CustomOptionTwo') that conforms to the same protocol 'PickerOption'. The compiler gives me two errors,
Type 'any PickerOption' cannot conform to 'Hashable'
Static method 'buildExpression' requires that 'Content' conform to 'AccessibilityRotorContent'
How can I achieve this?
Any help would be greatly appreciated.
protocol PickerOption: Hashable, Identifiable {
var name: String { get set }
var description: String { get set }
var id: String { get }
}
struct MyView: View {
//I know it's this line, but my array will consist of any object that conforms to PickerOption protocol
private static var exampleStructs: [any PickerOption] = [
CustomOptionOne(name: "Example 1", description: "Example Name 1", id: "5"),
CustomOptionOne(name: "Example 2", description: "Example Name 2", id: "6"),
CustomOptionTwo(name: "Example 3", description: "Example Name 3", id: "7"),
CustomOptionTwo(name: "Example 4", description: "Example Name 4", id: "8")
]
private struct CustomOptionOne: Hashable, Identifiable, PickerOption {
var name: String
var description: String
var id: String
}
private struct CustomOptionTwo: Hashable, Identifiable, PickerOption {
var name: String
var description: String
var id: String
}
@State private var selectedStruct: any PickerOption = CustomOptionOne(name: "Example Name", description: "Example Description", id: "9")
var body: some View {
NavigationView {
Form {
Section(header: Text("Selected Struct")) {
Text(selectedStruct.name)
Text(selectedStruct.description)
}
Section(header: Text("Picker")) {
Picker(selection: $selectedStruct, label: Text(selectedStruct.name), content: {
ForEach(MyView.exampleStructs, id: \.id) { exampleStruct in
Text(exampleStruct.name).tag(exampleStruct)
}
})
}
}
}
}
}
I've checked many answers including this swift picker not selecting item and none of them are answering my use case scenario.
For a
Pickerthetagand theselectionmust be of the exact same type your specific example adds an additional layer of complexity because you are trying to use existentials (any) with SwiftUI.So the simplest solution is to use the
IDfor both theselectionand thetagbut first you have to restrict theIDwhich comes fromIdentifiableto a specific type so you can match that for thePickerThen change the property to use a
StringThen change the
tagto match theselectedStructIdThe whole thing put together will look something like
I know this isn't ideal but existentials are an uphill battle with SwiftUI.