swiftuiuipickerviewuisegmentedcontrol

SwiftUI Segmented Picker not responding to user input


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?


Solution

  • 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()
        }
    }