SwiftUI SegmentedPicker切换测量类型时段数不更新及崩溃问题
问题根因
- Picker段数不同步:仅测量类型选择器添加了
.id(measurementType)强制重绘标识,输入单位Picker未添加该标识。SwiftUI默认会复用已有Picker视图,仅更新选项文本,不会重新渲染调整分段数量。 - 切换测量类型崩溃:
inputUnit的取值未与当前测量类型的单位数组长度绑定,例如初始选中长度类型(共5个单位,索引范围04)时`inputUnit`可能为3,切换到温度类型(仅3个单位,索引范围02)时,inputUnit=3超出当前单位数组的最大索引,触发数组越界崩溃。
修复代码
核心修改点:
- 为输入单位、输出单位Picker都添加
.id(measurementType),切换测量类型时强制重绘选择器,同步更新段数 - 添加
onChange修饰符监听measurementType变化,自动重置inputUnit和outputUnit到合法范围,避免越界 - 补充输出单位选择器的基础实现
struct ContentView: View { @State private var measurementType = 0 @State private var inputValue = "" @State private var inputUnit = 0 @State private var outputUnit = 1 let measurementTypes = ["Temp", "Length", "Time", "Volume"] var typeDictionary = [ ["Celsius", "Fahrenheit", "Kelvin"], ["Meters", "Kilometers", "Feet", "Yards", "Miles"], ["Seconds", "Minutes", "Hours", "Days"], ["Milliliters", "Liters", "Cups", "Pints", "Gallons"] ] var body: some View { NavigationView { Form { Section(header: Text("Choose the type of measurement")) { Picker("The type of measurement", selection: $measurementType) { ForEach(0 ..< measurementTypes.count, id: \.self) { Text("\(measurementTypes[$0])") } } .id(measurementType) .pickerStyle(SegmentedPickerStyle()) } Section { TextField("Enter the value", text: $inputValue) .keyboardType(.decimalPad) } Section(header: Text("Choose the input unit")) { Picker("The input unit", selection: $inputUnit) { ForEach(0 ..< typeDictionary[measurementType].count, id: \.self) { Text("\(typeDictionary[measurementType][$0])") } } .id(measurementType) .pickerStyle(SegmentedPickerStyle()) } Section(header: Text("Choose the output unit")) { Picker("The output unit", selection: $outputUnit) { ForEach(0 ..< typeDictionary[measurementType].count, id: \.self) { Text("\(typeDictionary[measurementType][$0])") } } .id(measurementType) .pickerStyle(SegmentedPickerStyle()) } Section(header: Text("Converted Value")) { Text("") } } } .onChange(of: measurementType) { newValue in // 切换测量类型时重置单位选择到合法范围,避免数组越界 let maxUnitIndex = typeDictionary[newValue].count - 1 inputUnit = 0 outputUnit = min(1, maxUnitIndex) } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
内容的提问来源于stack exchange,提问作者ManDag004
相关产品推荐
相关产品推荐

