SwiftUI中ForEach遍历Set时TextField输入中断的无@FocusState解决方案问询
问题解决说明
故障原因
- ForEach使用字符串元素本身作为ID,编辑时元素值变化触发ID变更,SwiftUI会重建对应的TextField视图,直接丢失输入焦点
- 原有绑定逻辑每输入一个字符就会修改Set,触发列表刷新,进一步导致输入中断
优化实现(无需@FocusState)
核心逻辑是拆分输入状态和数据源更新:编辑过程中输入内容仅存在行视图的本地状态,不修改Set,仅当用户按下回车键确认输入时才同步更新数据源,完全满足等待用户输入完成再更新的需求。
struct ContentView: View { @State private var set: Set<String> = ["value1", "value2", "value3", "value4"] var body: some View { SetforForEachWithBinding(set: $set) } } struct SetforForEachWithBinding: View { @Binding var set: Set<String> var body: some View { List { ForEach(set.sorted(by: <), id: \.self) { element in EditableRow(originalValue: element, set: $set) } } } } // 单独行视图,管理自身临时输入状态 struct EditableRow: View { let originalValue: String @Binding var set: Set<String> @State private var inputValue: String = "" var body: some View { TextField("Enter value here...", text: $inputValue, onCommit: { // 仅用户按下回车键提交时才更新Set guard !inputValue.isEmpty, inputValue != originalValue else { return } if set.contains(originalValue) { set.remove(originalValue) set.insert(inputValue) } }) .onAppear { inputValue = originalValue } } }
如果需要支持失去焦点自动同步修改,只需给TextField加上onEditingChanged回调,在编辑状态变为false时执行和onCommit相同的更新逻辑即可。
内容的提问来源于stack exchange,提问作者swiftPunk
相关产品推荐
相关产品推荐

