SwiftUI中关闭Picker弹窗并重置选中值至初始值的问题
你遇到的问题核心在于**initialPickerOption并没有真正保存打开Picker时的初始值**。
当你在ContentView里把selectedPickerOption直接传给PickerPopover的initialPickerOption时,因为selectedPickerOption是双向绑定到Picker的,只要你在Picker里滚动选择,这个值就会实时更新。这意味着当你点击Cancel按钮时,initialPickerOption已经变成了你刚才选中的新值,而不是打开Picker时的原始值,所以selectedPickerOption = initialPickerOption相当于把值设成了当前选中的那个,自然看不到重置效果。
方案一:在父视图中提前保存初始值
在打开Picker的瞬间,把当前选中的值保存到一个独立的State变量里,再传递给弹窗,确保这个值不会随着Picker的选择变化。
修改后的ContentView代码:
import SwiftUI struct ContentView: View { @State var showPicker = false @State var selectedPickerOption = 0 @State private var initialPickerValue = 0 // 新增:保存打开时的初始值 let pickerOptions = ["Hello", "World", "Yes"] var body: some View { ZStack { VStack { Text("Selected Option: \(pickerOptions[selectedPickerOption])") Button( action: { // 打开Picker前先保存当前选中值 initialPickerValue = selectedPickerOption showPicker = true }, label: { Text("Open Picker") .padding() } ) } if showPicker { PickerPopover( pickerOptions: pickerOptions, width: 300, height: 300, showPicker: $showPicker, selectedPickerOption: $selectedPickerOption, initialPickerOption: initialPickerValue // 传递保存好的初始值 ) .background(Color.red) } } } }
PickerPopover的代码不需要修改,现在点击Cancel时,就能正确把selectedPickerOption重置为打开Picker时的初始值了。
方案二:在弹窗内部保存初始值
让PickerPopover自己在出现时记录初始值,不需要父视图额外处理。
修改后的PickerPopover代码:
struct PickerPopover: View { var pickerOptions: [String] var width: CGFloat var height: CGFloat @Binding var showPicker: Bool @Binding var selectedPickerOption: Int @State private var initialPickerOption = 0 // 改成内部State func selectOption() { withAnimation { showPicker.toggle() } } func cancel() { selectedPickerOption = initialPickerOption withAnimation { showPicker.toggle() } } var body: some View { VStack { Picker( selection: $selectedPickerOption, label: Text("") ) { ForEach(0 ..< pickerOptions.count) { Text(self.pickerOptions[$0]) } } .pickerStyle(WheelPickerStyle()) Button(action: cancel) { Text("Cancel") } Button(action: selectOption) { Text("Select") } } .transition(.move(edge: .bottom)) .onAppear { // 弹窗出现时,记录当前的选中值(即打开时的初始值) initialPickerOption = selectedPickerOption } } }
这种方案下,ContentView里传递initialPickerOption的参数可以直接删掉,逻辑更简洁。
现在不管你在Picker里选了什么,点击Cancel都会把值重置为打开Picker时的原始状态,点击Select则保留新选中的值,完全符合你的需求。
内容的提问来源于stack exchange,提问作者matthias_code

