SwiftUI如何修复数组内TextField每输入一个字符就失焦的问题
问题根因
这个问题和Observable Object无关,完全是列表元素标识不稳定导致的重绘问题,具体问题点有两个:
- 你定义的
CmdOption结构体的id是计算属性,每次访问都会生成全新的UUID,无法作为元素的唯一稳定标识。 ForEach使用\.self作为元素的唯一标识,当你修改TextField绑定的value字段时,值类型的CmdOption实例的哈希值会发生变化,SwiftUI会判定原有元素被删除、新元素被插入,直接重建对应位置的TextField,导致输入框失去第一响应者状态(失焦)。
修复方案
只需修改两处即可解决问题:
- 将
CmdOption的id改为存储属性,初始化时生成一次即固定,保证元素标识不会随内容变化 - 移除
ForEach的id: \.self参数,直接使用Identifiable协议自带的稳定id作为列表元素标识
修复后完整可运行代码
struct CmdOption: Hashable, Identifiable { // id改为存储属性,初始化时生成一次固定不变 let id = UUID() var value: String } import SwiftUI struct ContentView: View { @State var theOptions: [CmdOption] = [ CmdOption(value: ""), CmdOption(value: "") ] @State var allOptions: [CmdOption] = [] var body: some View { VStack { ScrollView(.vertical) { // 移除id: \.self,直接用Identifiable的稳定id ForEach($allOptions) { $option in VStack { TextField(option.value, text: $option.value) } } } }.onAppear { startup() } } func startup() { allOptions.removeAll() theOptions.forEach {option in allOptions.append(option) } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
内容的提问来源于stack exchange,提问作者fawsha1
相关产品推荐
相关产品推荐

