SwiftUI删除列表项时确认对话框偶现弹出后消失问题求助
SwiftUI 删除列表单元格时确认对话框不稳定问题解决
问题根源
你遇到的对话框弹出后立即消失的问题,核心原因是确认对话框的附加位置错误:当前你把.confirmationDialog挂在List上,而删除操作会修改project.mirrors数组,触发List(包括内部的DisclosureGroup、ForEach)重新渲染。视图重建过程中,绑定的showingDeleteMirrorAlert状态可能被意外重置,或者对话框所在的视图层级被销毁,导致对话框直接消失。
解决步骤
1. 调整对话框的附加位置
将.confirmationDialog从List的修饰器移到整个视图的根层级(比如Form或者直接在body的最外层视图上),避免列表渲染影响对话框的生命周期。
2. 优化状态与对话框触发方式(可选但更可靠)
改用.confirmationDialog(item:)的形式,直接绑定要删除的Mirror对象,替代布尔值状态和IndexSet存储。这种方式依赖对象的存在性触发对话框,比isPresented更稳定,还能避免索引失效的问题。
修改后的完整代码
struct ProjectDetailView: View { let project: Project @Environment(\.modelContext) private var context @Environment(\.dismiss) private var dismiss // 改用可选对象存储要删除的镜像,替代IndexSet和布尔状态 @State private var mirrorToDelete: Mirror? var body: some View { Form { List { DisclosureGroup("Mirrors") { if project.mirrors.isEmpty { ContentUnavailableView { Image(systemName: "figure.strengthtraining.functional") Text("This project has no mirrors.") } description: { Text("Add some if you want some.") } } else { ForEach(project.mirrors) { mirror in NavigationLink(destination: MirrorDetailView(mirrors: mirror)) { MirrorCellView(mirror: mirror) } } .onDelete { indexSet in // 直接获取要删除的对象 if let index = indexSet.first { mirrorToDelete = project.mirrors[index] } } } } } } // 将对话框移到Form外层,脱离List的渲染影响 .confirmationDialog( "Are you sure you want to delete this mirror?", item: $mirrorToDelete, titleVisibility: .visible ) { mirror in Button("Delete", role: .destructive) { deleteMirror(mirror: mirror) mirrorToDelete = nil } Button("Cancel", role: .cancel) { mirrorToDelete = nil } } message: { _ in Text("This action cannot be undone.") } } // 直接接收Mirror对象,无需处理IndexSet private func deleteMirror(mirror: Mirror) { context.delete(mirror) do { try context.save() } catch { print("Error deleting mirror: \(error)") } } }
额外说明
- 原代码中用
IndexSet存储待删除项存在隐患:如果在对话框弹出期间列表数据发生变化(比如其他操作修改了数组),索引会失效,导致删除错误。直接存储对象则避免了这个问题。 - 对话框绑定到根视图后,即使列表重新渲染,对话框的生命周期也不会受影响,能稳定显示直到用户操作完成。
内容的提问来源于stack exchange,提问作者rhythmsticks
相关产品推荐
相关产品推荐

