如何解决在 SwiftUI 中将 TextField 与 ForEach 一起使用
我正在尝试使用 ForEach
显示文本字段的动态列表。以下代码按预期工作:我可以添加/删除文本字段,并且绑定正确。但是,当我在 items
视图模型中移动 ObservableObject
时,它不再工作,并因 index out of bounds
错误而崩溃。这是为什么?我怎样才能让它工作?
struct ContentView: View {
@State var items = ["A","B","C"]
var body: some View {
vstack {
ForEach(items.indices,id: \.self) { index in
FieldView(value: Binding<String>(get: {
items[index]
},set: { newValue in
items[index] = newValue
})) {
items.remove(at: index)
}
}
Button("Add") {
items.append("")
}
}
}
}
struct FieldView: View {
@Binding var value: String
let onDelete: () -> Void
var body: some View {
HStack {
TextField("item",text: $value)
Button(action: {
onDelete()
},label: {
Image(systemName: "multiply")
})
}
}
}
我尝试使用的视图模型:
class viewmodel: Observable {
@Published var items: [String]
}
@Observedobject var viewmodel: viewmodel
我发现很多问题都涉及相同的问题,但我无法解决我的案例。其中一些没有提到 TextField
,其他一些不起作用(不再起作用?)。
非常感谢
解决方法
通过检查 Binding
内的边界,您可以解决问题:
struct ContentView: View {
@ObservedObject var viewModel: ViewModel = ViewModel(items: ["A","B","C"])
var body: some View {
VStack {
ForEach(viewModel.items.indices,id: \.self) { index in
FieldView(value: Binding<String>(get: {
guard index < viewModel.items.count else { return "" } // <- HERE
return viewModel.items[index]
},set: { newValue in
viewModel.items[index] = newValue
})) {
viewModel.items.remove(at: index)
}
}
Button("Add") {
viewModel.items.append("")
}
}
}
}
这是一个 SwiftUI 错误,例如类似于 this 的问题。
,我无法完美解释导致崩溃的原因,但我已经能够重现该错误,并且在删除字段后,SwiftUI
仍在寻找所有 indices
以及何时它试图访问已删除索引处的元素,但无法找到它,从而导致 index out of bounds
错误。
为了解决这个问题,我们可以编写一个条件语句来确保仅当 element
包含在 index
的集合中时才搜索 indices
。
FieldView(value: Binding<String>(get: {
if viewModel.items.indices.contains(index) {
return viewModel.items[index]
} else {
return ""
}
},set: { newValue in
viewModel.items[index] = newValue
})) {
viewModel.items.remove(at: index)
}
上面的解决方案解决了这个问题,因为它确保当元素数(items.count
)不大于index
时不会搜索元素。
这只是我能够理解的,但在幕后可能还有其他事情发生。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。