Reputation: 269
I have 4 dogs - represented by 4 Pickers - and each one of them has a favourite treat. How can I store the selection of each Picker? I tried storing it in a dictionary, but when clicking on one of the treats nothing gets selected and the Picker view also does not get dismissed.
import SwiftUI
import OrderedCollections
enum Dog : String, CaseIterable, Identifiable {
var id: Self { self }
case Anton, Ben, Charlie, Didi
}
struct MainConstants {
let treats : OrderedDictionary <String, Int> = [
"Bone" : 123,
"Sausage" : 456,
"Cookies" : 789
]
}
struct FavouriteTreatsView: View {
let constants = MainConstants()
@State var favouriteTreats : [Dog : String] = [:]
var body: some View {
NavigationView {
Form {
ForEach (Dog.allCases) {dog in
Picker(dog.rawValue ,selection: $favouriteTreats[dog]) {
ForEach (constants.treats.keys, id: \.self) {treat in
Text(treat)
}
}
}
}
}
}
}
struct FavoriteTreatsView_Previews: PreviewProvider {
static var previews: some View {
FavouriteTreatsView()
}
}
Upvotes: 0
Views: 668
Reputation: 4006
I don't know about treating dogs, however the example below works well with lions...
First, you can have a dedicated view for each single picker - that view will store the treat of each lion on a @State
var. You use the .id()
modifier to tell the picker what value needs to be stored.
The view will also have a @Binding
var that will receive the dictionary, to store the treat selected on the right lion.
In that picker view, you listen to changes in the treat: when a treat is selected, you store that value in the dictionary passed with the binding var.
So, assuming they are lions, here's the picker view:
struct TreatMe: View {
let constants = MainConstants()
// treat for a single Lion
@State private var treat = ""
// The dictionary that will be updated after the treat is selected
@Binding var favouriteTreats: [Lion: String]
// the Lion that will receive the treat
let lion: Lion
var body: some View {
Picker(lion.rawValue ,selection: $treat) {
ForEach (constants.treats.keys, id: \.self) {treat in
Text(treat)
// This will ensure the right value is stored
.id(treat)
}
}
// Listen to changes in the treat, then store it in the dictionary
.onChange(of: treat) { value in
favouriteTreats[lion] = value
}
}
}
You call it from the FavouriteTreatsView
:
struct FavouriteTreatsView: View {
@State var favouriteTreats : [Lion : String] = [:]
var body: some View {
NavigationView {
Form {
ForEach (Lion.allCases) {lion in
// Pass the variables
TreatMe(favouriteTreats: $favouriteTreats, lion: lion)
}
}
}
}
}
Upvotes: 1