You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

枚举ForEach中使用onSubmit无法获取正确索引的问题

ForEach中onSubmit索引异常的原因与修复

问题根源

索引始终为0的核心原因是SwiftUI视图身份识别逻辑混乱:

  • 你通过Array(vm.numberOfResistors.enumerated())生成枚举数组,同时将id: \.offset作为视图唯一标识。但offset是数组的临时索引,当数组元素增删、顺序变化时,SwiftUI会复用现有视图,导致onSubmit闭包捕获的index停留在旧值(比如始终为0)。
  • onChange能正常工作是因为它绑定了resistor元素本身,元素变化时会触发对应视图的回调,不受视图复用的影响。

另外代码中同时使用dummyVM和vm两个视图模型,这种状态不一致也可能加剧视图渲染的混乱,建议统一使用同一个模型。

修复方案

方案1:让模型遵循Identifiable(推荐)

如果你的Resistor结构体可以修改,让它遵循Identifiable协议,这样SwiftUI能通过元素唯一ID跟踪视图:

struct Resistor: Identifiable {
    let id = UUID() // 添加唯一ID
    var valueString: String
    var unit: String
    var value: Double
}

然后修改ForEach的写法:

ForEach($vm.numberOfResistors) { $resistor in
    guard let index = vm.numberOfResistors.firstIndex(where: { $0.id == resistor.id }) else {
        return
    }
    UnitTextField(
        title: "Resistor \(index + 1)",
        value: $resistor.valueString,
        unit: $resistor.unit,
        focusField: $focusField,
        fieldType: "resistor \(index + 1)"
    ).onSubmit {
        let nextIndex = index + 1
        if nextIndex < vm.numberOfResistors.count {
            print(nextIndex)
            focusField = "resistor \(nextIndex + 1)"
        } else {
            print("2")
            focusField = nil
        }
    }.onChange(of: resistor) { _, newValue in
        resistor.value = Constants.convertToCoulomb(from: newValue.unit, value: Double(newValue.valueString) ?? 0)
    }
}.padding(.bottom)

方案2:直接遍历数组索引(无需修改模型)

如果无法修改Resistor模型,直接遍历数组的indices,用索引本身作为视图ID,确保每个视图的索引稳定:

ForEach(vm.numberOfResistors.indices, id: \.self) { index in
    let resistor = vm.numberOfResistors[index]
    UnitTextField(
        title: "Resistor \(index + 1)",
        value: $vm.numberOfResistors[index].valueString,
        unit: $vm.numberOfResistors[index].unit,
        focusField: $focusField,
        fieldType: "resistor \(index + 1)"
    ).onSubmit {
        let nextIndex = index + 1
        if nextIndex < vm.numberOfResistors.count {
            print(nextIndex)
            focusField = "resistor \(nextIndex + 1)"
        } else {
            print("2")
            focusField = nil
        }
    }.onChange(of: resistor) { _, newValue in
        vm.numberOfResistors[index].value = Constants.convertToCoulomb(from: newValue.unit, value: Double(newValue.valueString) ?? 0)
    }
}.padding(.bottom)

内容的提问来源于stack exchange,提问作者Mark George

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 15:33:42