You need to enable JavaScript to run this app. SwiftUI SegmentedPicker切换测量类型时段数不更新及崩溃问题
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI SegmentedPicker切换测量类型时段数不更新及崩溃问题

问题根因

  • Picker段数不同步:仅测量类型选择器添加了.id(measurementType)强制重绘标识,输入单位Picker未添加该标识。SwiftUI默认会复用已有Picker视图,仅更新选项文本,不会重新渲染调整分段数量。
  • 切换测量类型崩溃:inputUnit的取值未与当前测量类型的单位数组长度绑定,例如初始选中长度类型(共5个单位,索引范围04)时`inputUnit`可能为3,切换到温度类型(仅3个单位,索引范围02)时,inputUnit=3超出当前单位数组的最大索引,触发数组越界崩溃。

修复代码

核心修改点:

  1. 为输入单位、输出单位Picker都添加.id(measurementType),切换测量类型时强制重绘选择器,同步更新段数
  2. 添加onChange修饰符监听measurementType变化,自动重置inputUnit和outputUnit到合法范围,避免越界
  3. 补充输出单位选择器的基础实现
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.20 07:54:09