枚举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
相关产品推荐
相关产品推荐

