当我使用 onDelete()
删除数组的元素时,它会删除数据中的正确项目,但会删除 UI 上的最后一个项目。我看到this answer但我已经在使用它推荐的东西了。有什么建议吗?
struct ContentView: View {
@State var items = ["One", "Two", "Three"]
var body: some View {
Form{
ForEach(items.indices, id:\.self){ itemIndex in
let item = self.items[itemIndex]
EditorView(container: self.$items, index: itemIndex, text: item)
}.onDelete(perform: { indexSet in
self.items.remove(atOffsets: indexSet)
})
}
}
}
这是 EditorView 结构:
struct EditorView : View {
var container: Binding<[String]>
var index: Int
@State var text: String
var body: some View {
TextField("Type response here", text: self.$text, onCommit: {
self.container.wrappedValue[self.index] = self.text
})
}
}
最佳答案
您的 ForEach
正在循环遍历数组的索引
,因此这就是 SwiftUI
用于识别它们的方法。当您删除一项时,数组的索引就会减少一个,因此 SwiftUI 会将其解释为最后一个已被删除。
要正确执行此操作,您应该循环遍历具有唯一id
的可识别
项列表。在这里,我创建了一个名为 MyItem
的 struct
,它保存原始 String
和唯一生成的 id
。我使用 .map(MyItem.init)
将项目转换为 [MyItem]
。
此外,您的代码需要循环中的索引,因此循环 Array(items.enumerated())
这将为您提供一个 (offset, element)
数组> 元组。然后告诉 SwiftUI 使用 \.element.id
作为 id
。
请注意,EditorView
现在采用 MyItem
数组。
通过这些更改,SwiftUI 将能够识别您从列表中删除的项目并正确更新 UI。
struct MyItem: Identifiable {
var name: String
let id = UUID()
}
struct ContentView: View {
@State var items = ["One", "Two", "Three"].map(MyItem.init)
var body: some View {
Form{
ForEach(Array(items.enumerated()), id: \.element.id) { index, item in
EditorView(container: self.$items, index: index, text: item.name)
}.onDelete(perform: { indexSet in
self.items.remove(atOffsets: indexSet)
})
}
}
}
struct EditorView : View {
var container: Binding<[MyItem]>
var index: Int
@State var text: String
var body: some View {
TextField("Type response here", text: self.$text, onCommit: {
self.container.wrappedValue[self.index].name = self.text
})
}
}
关于SwiftUI:onDelete 无法正确更新 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64241987/