SwiftUI中TextField绑定值无法随Stepper更新问题求助
问题分析与解决方案
核心问题1:Equatable实现逻辑完全错误
StackOverFlowExampleModel的==方法写反了判断逻辑:
static func == (lhs: StackOverFlowExampleModel, rhs: StackOverFlowExampleModel) -> Bool { lhs.id != rhs.id // 此处应为 == }
这个错误会导致SwiftUI无法正确识别模型实例的变化——当你修改item.value时,SwiftUI会错误地认为模型没有发生改变,进而不会更新TextField的显示内容。
核心问题2:原始值(ogVal)的记录时机不合理
当前ogVal仅在视图onAppear时赋值,若用户手动修改TextField数值后再使用Stepper,ogVal仍会保留初始的45.0,而非用户更新后的最新值,导致计算逻辑不符合预期。
其他优化点
onChange(of: numberOfPeople)无需嵌套在TextField的修饰符中,直接放在视图层级内逻辑更清晰;- 未使用的
@State var val = Decimal()可删除,减少冗余代码。
修正后的代码
1. 修正Equatable实现的StackOverFlowExampleModel
struct StackOverFlowExampleModel: Identifiable, Equatable { static func == (lhs: StackOverFlowExampleModel, rhs: StackOverFlowExampleModel) -> Bool { lhs.id == rhs.id // 修正为正确的相等判断 } let id = UUID() var name: String var value: Decimal? var hasFocus: Bool = false var selected: (Bool, Color) = (false, .clear) }
2. 调整逻辑的ExtractedTextField
struct ExtractedTextField: View { @Binding var inFocus: Field? @State var numberOfPeople = 1 @Binding var item: StackOverFlowExampleModel @FocusState private var focus: Bool @State var ogVal = Decimal() var body: some View { VStack { HStack { TextField("Item", text: $item.name, prompt: Text("Item name")) .textFieldStyle(.roundedBorder) Spacer() TextField("Value", value: $item.value, format: .currency(code: "USD")) .textFieldStyle(.roundedBorder) .focused($focus) } if focus { HStack { Stepper(value: $numberOfPeople) { Text("Split between \(numberOfPeople) people") } } } } .onChange(of: focus) { isFocused in if isFocused { // 获得焦点时记录当前值作为分割计算的原始值 ogVal = item.value ?? 0.0 inFocus = .fieldId(item.id) } } .onChange(of: numberOfPeople) { newValue in // 根据人数更新分割后的值 item.value = ogVal / Decimal(newValue) } .focused($focus) .id(item.id) } }
修正后效果说明
- 修正Equatable逻辑后,SwiftUI能正确检测
item.value的变化,TextField会实时显示计算后的数值; - 仅在TextField获得焦点时记录原始值,确保分割计算使用的是当前最新的输入值;
- 调整
onChange的位置,让代码逻辑更直观易读。
内容的提问来源于stack exchange,提问作者Eric Agredo
相关产品推荐
相关产品推荐

