You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过.onDelete方法可靠地从SwiftData容器中删除数据?

问题:SwiftData批量删除Report后数据回滚的异常情况

我是iOS开发新手,对SwiftData完全陌生,希望这不是个蠢问题。

我的SwiftData数据模型是一对多再到多的结构:一个Project包含多个Report,每个Report包含多个Item;Project的Report仅属于该Project,Report的Item仅属于该Report。

遇到的问题:将特定Project的Report列表传入List的ForEach视图,使用.onDelete方法删除Report时,经常出现删除后的Report在导航离开再返回、或关闭应用后重新出现的情况。这个问题不是每次都发生,且仅在删除2个及以上Report时出现。

相关代码

ActiveReports视图

import SwiftUI
import SwiftData

struct ActiveReports: View {
    @Environment(\.modelContext) private var context
    @State private var alertSaveError = false

    let projectReports: [Report]
    
    var body: some View {
        Group {
            List {
                ForEach(projectReports) { report in
                    NavigationLink {
                        ReportListView(report: report)
                    } label: {
                        HStack{
                            Text("\(report.scope)")
                            Text("Version: \(report.version)")
                            Spacer()
                            Text("\(report.dateCreated.formatted(date: .abbreviated, time:
                                .omitted))")
                        }
                    }
                }
                .onDelete(perform: deleteReport)
            }
        }
        .alert("Failed to Save", isPresented: $alertSaveError ){
            Button("OK", role: .cancel) { }
        }
    }
    
    func deleteReport(_ indexSet: IndexSet) {
        for item in indexSet {
            let report = projectReports[item]
            context.delete(report)
            do{
                try context.save()
            } catch {
                alertSaveError = true
                print("Error in saving")
            }
        }
    }
}

Project模型

import Foundation
import SwiftData

@Model
class Project {
    var name: String = ""
    var projectNumber: String = ""
    var scopes: [String] = [""]
    
    init(name: String, projectNumber: String, scopes: [String]) {
        self.name = name
        self.projectNumber = projectNumber
        self.scopes = scopes

    }
    
    @Relationship(deleteRule: .cascade)
    var reports: [Report]? = []
}

Report模型

import Foundation
import SwiftData

@Model
class Report {
    var version: Int = 1
    var scope: String = ""
    var dateCreated: Date = Date.now
    var issued: Bool = false
    
    init(version: Int, scope: String, issued: Bool) {
        self.version = version
        self.scope = scope
        self.issued = issued
    }
    
    // Setting the relationship back to parent Project
    @Relationship(inverse: \Project.reports)
    var project: Project?
    
    //Setting up the related punch items
    @Relationship(deleteRule: .cascade)
    var punchItems: [PunchItem]?
}

已尝试的解决方案

  • 使用@Query宏获取Report列表,删除操作可靠,但会显示所有Project的Report;尝试过滤Query结果,无法实现动态过滤(传入Project名称仅获取其Report)。
  • 强制保存模型容器,未出现保存失败,但问题依旧。
  • 查阅资料发现类似行为是旧版本已知Bug(理论已修复),强制保存是临时方案,但对我无效。

我认为是自己的逻辑问题,但搞不懂为什么用@Query宏时删除可靠,传入数组时只有约50%的成功率。

编辑:把.onDelete方法改成ForEach项内的.swipeActions后,删除行为恢复正常,不确定是Bug还是自己理解不到位。


内容的提问来源于stack exchange,提问作者Dillonmk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 03:34:59