SwiftUI List内嵌TextField无法连续输入字符问题求助
问题原因
你的代码确实存在逻辑错误,问题出在ForEach的唯一标识选择上:
你当前使用ForEach($viewModel.options, id: \.self),将字符串本身的值作为元素的唯一id。每次你修改TextField绑定的字符串内容时,该元素的id就会同步变化,SwiftUI会判定原有行已被销毁、新增了一个陌生行,因此触发整行重绘,原本处于激活状态的TextField会失去第一响应者身份,自然无法连续输入,必须重新点击激活才能输入下一个字符。
修复方案
推荐使用带稳定唯一标识的方案,标识不会随内容修改发生变化,适配所有增删改场景:
- 自定义带固定唯一id的选项结构体
struct Option: Identifiable { // 生成后不会变化的唯一id let id = UUID() // 存储输入的文本内容 var content: String }
- 修改ViewModel的数组元素类型
class PieChartViewModel: ObservableObject, Identifiable { @Published var options = [ Option(content: "How are you"), Option(content: "你好"), Option(content: "Let's go to zoo"), Option(content: "OKKKKK"), Option(content: "什麼情況??"), Option(content: "yesssss"), Option(content: "二百五"), Option(content: "明天見") ] }
- 调整视图层的ForEach和绑定逻辑
struct OptionsView: View { @ObservedObject var viewModel: PieChartViewModel var body: some View { NavigationView { List { // 因为Option遵守Identifiable协议,无需手动指定id,自动使用固定的id属性作为唯一标识 ForEach($viewModel.options) { $option in TextField(option.content, text: $option.content) } } .navigationTitle("Options") .toolbar { ToolbarItem(placement: .bottomBar) { Button { addNewOption() } label: { HStack { Image(systemName: "plus") Text("Create a new option") } } } } } } func addNewOption() { viewModel.options.append(Option(content: "")) } }
如果仅做临时测试,不会对数组做中间插入、删除操作,也可以用下标作为临时id,仅修改ForEach写法即可:
ForEach($viewModel.options.indices, id: \.self) { index in TextField(viewModel.options[index], text: $viewModel.options[index]) }
注意:该临时方案仅适合不会增删数组中间元素的场景,否则会出现标识错乱导致的显示异常。
内容的提问来源于stack exchange,提问作者
相关产品推荐
相关产品推荐

