I've got pickers working with a static list of items.
I am stuck on how to populate them using dynamic data (from an @state variable or an environment variable.)
This dirt-simple SwiftUI app creates a segmented control, but it doesn't show a current selection and won't allow the user to select one:
import SwiftUI
struct ContentView: View {
@State private var colors = ["Red", "Green", "Blue"]
@State private var selectedColor: Int = 0
var body: some View {
VStack {
HStack {
Spacer().frame(width: 30)
Picker("What is your favorite color?", selection: $selectedColor) {
ForEach(colors, id: \.self) { aValidColor in
Text(aValidColor)
}
}
Spacer().frame(width: 30)
}
.pickerStyle(.segmented)
Spacer().frame(height: 30)
Text("Value: \(colors[selectedColor])")
}
}
}
(I'm using Xcode 15.0 beta 3, if that matters.)
I gather it has something to do with the ids of the items in my ForEach and the tag values that get assigned to the Text items in the Picker, but I can't figure out how to make it work.
Edit:
I got it to work by changing from an Array of String objects to an array of Identifiable Structs, and having the id of each struct be its index in the array:
import SwiftUI
struct AColor: Identifiable {
let name: String
let id: Int
}
struct ContentView: View {
@State private var colors = [
AColor(name: "Red", id: 0),
AColor(name:"Green", id: 1),
AColor(name:"Blue", id: 2)
]
@State private var selectedColor: Int = 0
var body: some View {
VStack {
HStack {
Spacer().frame(width: 30)
Picker("What is your favorite color?", selection: $selectedColor) {
ForEach(colors) { aValidColor in
Text(aValidColor.name)
}
}
Spacer().frame(width: 30)
}
.pickerStyle(.segmented)
Spacer().frame(height: 30)
Text("Value: \(colors[selectedColor].name)")
}
}
}
That is less than ideal though, since now I have to maintain an array of structs where each item in the array has a value that contains its index in the array. Ugh.
It seems like there should be some way to use enumerated() to get an array of objects and their indexes, but ForEach wants a Binding, not an enumerated sequence. (I'm still trying to wrap my head around bindings.)