SwiftUI:onDelete 无法正确更新 UI

标签 swiftui

当我使用 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可识别 项列表。在这里,我创建了一个名为 MyItemstruct,它保存原始 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/

相关文章:

swiftui - 在通过 NavigationLink 导航到其他 View 之前,我该怎么做?

uitableview - TableView 重新加载不适用于 SwiftUI 中的 UIViewRepresentable

swift - 无法使用 RealityKit 场景预览 SwiftUI Canvas

ios - UIViewRepresentable 自动大小 - 将 UIKit UIView 大小传递给 SwiftUI

ios - SwiftUI 列表仅使用给定数组的第一项

ios - xcode预览无法构建到项目中

swift - 在 SwiftUI 中使用 Tab Bar 弹出到 Root View

SwiftUI 按钮文本居中

SwiftUI:基于@Published 变量对列表进行排序

ios - iOS 框架内使用的图像未在测试应用程序上加载