在SwiftUI分组表中按下编辑模式按钮之前,不会删除行

在SwiftUI分组表中按下编辑模式按钮之前,不会删除行,swiftui,swiftui-list,Swiftui,Swiftui List,我在SwiftUI中使用ObservableObject作为数据源实现了一个分组表。嵌套的ForEach用于生成每个节。EditMode()按钮用于切换该环境属性。在编辑模式下,删除操作完成后,删除的行(意外地)仍保留在屏幕上。(即使该对象已从数据源数组中删除。)当用户返回到正常查看模式时,该对象将延迟从表中删除 为了追踪bug,请执行以下操作: 数据源对象符合可散列、可识别和可均衡的规则 实现了一个简单的删除操作(即 删除@Published属性中的第一个对象) 数据源/视图模型存储在@E

我在SwiftUI中使用ObservableObject作为数据源实现了一个分组表。嵌套的ForEach用于生成每个节。EditMode()按钮用于切换该环境属性。在编辑模式下,删除操作完成后,删除的行(意外地)仍保留在屏幕上。(即使该对象已从数据源数组中删除。)当用户返回到正常查看模式时,该对象将延迟从表中删除

为了追踪bug,请执行以下操作:

  • 数据源对象符合可散列、可识别和可均衡的规则

  • 实现了一个简单的删除操作(即 删除@Published属性中的第一个对象)

  • 数据源/视图模型存储在@EnvironmentData对象中

因此,简单的问题是,我做错了什么,导致SwiftUI无法在一个非常简单(我认为)分组(按节)的列表上立即反映EditMode中的删除操作

struct ContentView:View{
@EnvironmentObject变量vm:AppData
var body:一些观点{
导航视图{
名单{
中的ForEach(vm.folderSource){(文件夹:folder)
返回部分(标题:文本(文件夹标题)){
//这就是问题的根源。当我放入一个新的完整视图结构时,当从这个嵌套视图调用.onDelete时,UI更新停止正常工作
FolderView(文件夹:文件夹)
}
}
}.listStyle(GroupedListStyle())
.navigationBarItems(尾部:EditButton())
}
}
}
结构FolderView:视图{
var文件夹:文件夹
@EnvironmentObject变量vm:AppData
var body:一些观点{
//我在外部ForEach循环中使用专用视图,以便能够访问每个动态视图的数据源。
让associatedProjects=vm.projects.filter{$0.folder==folder}
返回ForEach(关联项目){(项目:项目)中的
文本(project.title.uppercased())
//简化删除,以消除阻止准确动态视图更新的其他可能问题
}.onDelete{self.vm.delete()中的索引]
}
}
//视图模型
类AppData:ObservableObject{
let folderSource:[文件夹]
@已发布的var项目:[项目]
func delete(){
//简化静态删除调用以尝试查找ui错误
self.projects.remove(位于:0)
//
}
init(){
let folders=[文件夹(标题:“folder1”,显示顺序:0),文件夹(标题:“folder2”,显示顺序:1),文件夹(标题:“folder3”,显示顺序:2)]
self.folderSource=文件夹
self.projects={
var tempArray=[Project]()
append(项目(标题:“项目0”,显示顺序:0,文件夹:文件夹[0]))
append(项目(标题:“项目1”,显示顺序:1,文件夹:文件夹[0]))
append(项目(标题:“项目2”,显示顺序:2,文件夹:文件夹[0]))
append(项目(标题:“项目3”,显示顺序:0,文件夹:文件夹[1]))
append(项目(标题:“项目4”,显示顺序:1,文件夹:文件夹[1]))
append(项目(标题:“项目5”,显示顺序:2,文件夹:文件夹[1]))
append(项目(标题:“项目6”,显示顺序:0,文件夹:文件夹[2]))
append(项目(标题:“项目7”,显示顺序:1,文件夹:文件夹[2]))
append(项目(标题:“项目8”,显示顺序:2,文件夹:文件夹[2]))
返回临时数组
}()
}
}
//子实体多对一(文件夹)
类项目:可散列、可均衡、可识别{
设id=UUID()
标题:字符串
让显示顺序:Int
让文件夹:文件夹
init(标题:String,显示顺序:Int,文件夹:folder){
self.title=标题
self.displayOrder=displayOrder
self.folder=文件夹
}
静态函数==(左:项目,右:项目)->Bool{
lhs.id==rhs.id
}
func散列(放入散列程序:inout散列程序){
hasher.combine(id)
}
}
//父实体:许多项目都有一个文件夹
类文件夹:可散列、可均衡、可识别{
设id=UUID()
标题:字符串
让显示顺序:Int
init(标题:String,显示顺序:Int){
self.title=标题
self.displayOrder=displayOrder
}
//使相等
静态函数==(左:文件夹,右:文件夹)->Bool{
lhs.id==rhs.id
}
//使散列
func散列(放入散列程序:inout散列程序){
hasher.combine(id)
}
}
在SceneDelegate.斯威夫特

//创建提供窗口内容的SwiftUI视图。
让contentView=contentView().environmentObject(AppData())

我删除了我以前的答案,因为正如你所指出的,尽管它有效,但这纯粹是巧合

这是你的另一份工作。它基本上是通过而不是封装第二个ForEach来工作的。到目前为止,我发现封装是避免某些bug的好工具。在这种情况下,情况正好相反

struct ContentView:View{
@EnvironmentObject变量vm:AppData
var body:一些观点{
导航视图{
名单{
中的ForEach(vm.folderSource){(文件夹:folder)
节(标题:文本(文件夹标题)){
//FolderView(文件夹:文件夹)
中的ForEach(self.vm.projects.filter{$0.folder==folder}){(project:project)
文本(project.title.uppercased())
}.onDelete{index中的索引
self.vm.delete()
}
}
}
}
.listStyle(GroupedListStyle())