Iam trying to use Picker as selection of struct. Let say I have a struct "Pet" like below
struct Pet: Identifiable, Codable, Hashable {
let id = UUID()
let name: String
let age: Int
}
I am getting all Pet's from some class, where Pets are defined as @Published var pets = Pet
static let pets = Class().pets
I would like to be able to write a selection from picker to below variable:
@State private var petSelection: Pet?
Picker is:
Picker("Pet", selection: $petSelection){
ForEach(Self.pets) { item in
Text(item.name)
}
}
Picker shows properly all avaliavble pets but when I chose one petSelection has been not changed (nil). How should I mange it?
Thanks!
Edit:
Of course I know that I can use tag like below:
Picker("Pet", selection: $petSelection) {
ForEach(0 ..< Self.pet.count) { index in
Text(Self.pet[index].name).tag(index)
}
But wonder is it possible to use struct as selection. Thanks
Short answer: The type associated with the tag of the entries in your Picker (the Texts) must be identical to the type used for storing the selection.
From Picker docs:
Use an optional value for the selection input parameter. For that to work, you need to explicitly cast the tag modifier’s input as Optional to match. For an example of this, see tag(_:).
In your example: You have an optional selection (probably to allow "empty selection") of Pet?, but the array passed to ForEach is of type [Pet]. You have to add therefore a .tag(item as Pet?) to your entries to ensure the selection works.
ForEach(Self.pets) { item in
Text(item.name).tag(item as Pet?)
}
Here follows my initial, alternate answer (getting rid of the optionality):
You have defined your selection as an Optional of your struct: Pet?. It seems that the Picker cannot handle Optional structs properly as its selection type.
As soon as you get rid of the optional for example by introducing a "dummy/none-selected Pet", Picker starts working again:
extension Pet {
static let emptySelection = Pet(name: "", age: -1)
}
in your view initialise the selection:
@State private var petSelection: Pet = .emptySelection
I hope this helps you too.
You use the following way:
@Published var pets: [Pet?] = [ nil, Pet(name: "123", age: 23), Pet(name: "123dd", age: 243),]
VStack{
Text(petSelection?.name ?? "name")
Picker("Pet", selection: $petSelection){
ForEach(Self.pets, id: \.self) { item in
Text(item?.name ?? "name").tag(item)
}}}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With