I have a segmented picker control that is dynamically generated from my model's values. I have made a minimal reproducible example, and here is the model:
class DataModel: ObservableObject {
@Published var myObject: Objet = setUpObject
}
let setUpObject: Objet = {
var theObject = Objet(
name: "The Only Object",
descriptionActive: "Segmented picker choices",
objectTypes: [.choice1, .choice2, .choice3])
return theObject
}()
struct Objet: Hashable, Identifiable {
let id = UUID()
var name: String
var descriptionActive: String
var objectTypes: [ObjectType]
}
// the different default types
enum ObjectType: Int, Identifiable {
case none
case choice1
case choice2
case choice3
var id: Int { rawValue }
var localizedName: LocalizedStringKey {
switch self {
case .none:
return "Error"
case .choice1:
return "Choice 1"
case .choice2:
return "Choice 2"
case .choice3:
return "Choice 3"
}
}
}
And here is the View that renders the picker:
struct ContentView: View {
@StateObject private var dataModel = DataModel()
@State private var selectedType = "Missing"
var body: some View {
VStack {
Text(dataModel.myObject.descriptionActive)
Divider()
Picker("Which type?", selection: $selectedType) {
ForEach(dataModel.myObject.objectTypes) { type in
Text(type.localizedName)
}
}
.pickerStyle(SegmentedPickerStyle())
Text("Value: \(selectedType)")
}
.padding()
}
}
With this, the picker does not update on user tapping on it, and the Text view below remains at "Missing". What is wrong here?
Your selectedType
and tag
on the Picker
items have to match:
struct ContentView: View {
@StateObject private var dataModel = DataModel()
@State private var selectedType: ObjectType = .choice1 //<-- Here
var body: some View {
VStack {
Text(dataModel.myObject.descriptionActive)
Divider()
Picker("Which type?", selection: $selectedType) {
ForEach(dataModel.myObject.objectTypes) { type in
Text(type.localizedName).tag(type) //<-- Here
}
}
.pickerStyle(SegmentedPickerStyle())
Text(selectedType.localizedName)
}
.padding()
}
}