Home > Software design >  swiftui change shown picker value
swiftui change shown picker value

Time:07-20

Hello I have made a picker in swiftUI where the user has to accept the change on the picker.

It works well, but there is one issue. If the user selects something and then declines the change, the shown value will still be what was selected though the actual value doesn't change.

If I open the picker again without selecting anything it reverts back to the right value but how to I do this without having to open the picker?

struct ContentView: View {
@State private var selectedColorIndex = "cd"
@State private var temp = ""
@State var alert = false

private var colors = ["ab", "cd", "ef", "gh", "ij", "kl", "mn", "op", "qr", "st", "uv", "wx", "yz"]
var body: some View {
    
    
    HStack {
        Text("Location")
        Picker("Location", selection: Binding(get: {selectedColorIndex}, set: {
            temp = $0
            alert = true
        })) {
            ForEach(colors, id: \.self) {
                Text($0)
            }
        }.pickerStyle(MenuPickerStyle())
        
    }.alert(isPresented: $alert) {
        Alert(title: Text("are you sure"), primaryButton: .default(Text("yes"), action: {
            selectedColorIndex = temp
            
            
        }), secondaryButton: .default(Text("no"), action: {
            
            //change shown value back to prev selectedColorIndex
        }))
    }
    
}

}

CodePudding user response:

This does not work because the PickerView does not refresh with the value it gets from the binding. Adding a print statement in the binding confirms, that it indeed delivers the correct value.

A simple solution to this would be to force the Picker to refresh itself every time the body of the ContentView gets reavaluated. We can achieve this by manually changing the id of the Picker.

var body: some View {
    HStack {
        Text("Location")
        Picker("Location", selection: Binding(get: {selectedColorIndex}, set: {
            temp = $0
            alert = true
        })) {
            ForEach(colors, id: \.self) {
                Text($0)
            }
        }
        .id(UUID()) // add this
        .pickerStyle(MenuPickerStyle())
            
        
    }.alert(isPresented: $alert) {
        Alert(title: Text("are you sure"), primaryButton: .default(Text("yes"), action: {
            selectedColorIndex = temp
            
            
        }), secondaryButton: .default(Text("no"), action: {
            // No code needed here
            //change shown value back to prev selectedColorIndex
        }))
    }
}

If you want to know more why this works you can read my answer here: more info

  • Related