删除数据

温馨提示:本文最后更新于2025-01-19 17:01:30,某些文章具有时效性,若有错误或已失效,请在下方留言

删除 SwiftData 对象需要两个步骤:首先在你的模型上下文上调用 delete()方法,并传入你想要删除的对象;然后保存更改,可以通过显式调用 save(),或者如果启用了自动保存,则等待自动保存触发。

因此,对于单个对象,你可以这样编写代码:

struct ContentView: View {
    @Environment(\.modelContext) private var context
    var body: some View {
        List(students) { student in
            Text(student.name)
                .swipeActions {
                    Button("Delete", systemImage: "trash", role: .destructive) {
                        context.delete(student)
                    }
                }
        }
    }
}

如果你正在处理一个对象集合,你需要使用类似于以下的 for 循环:

func delete(_ indexSet: IndexSet) {
    for i in indexSet {
        let student = students[i]
        modelContext.delete(student)
    }
}

如果你想删除特定模型类型的所有对象,可以使用 delete(model:) 重载,如下所示:

do {
    try modelContext.delete(model: School.self)
} catch {
    print("Failed to delete all schools.")
}

如果你只想删除对象的一个子集,可以使用带有谓词的 delete(model:),如下所示:

try modelContext.delete(
    model: School.self,
    where: #Predicate { school in
        school.students.isEmpty
    }
)

调用 delete()会将对象标记为待删除,但实际删除需要调用 save()。在此之前,对象会存储在 deletedModelsArray 中,如果删除被回滚,对象会恢复到实时数据中。如果禁用自动保存且未手动调用 save(),删除将自动回滚。

在删除有关系的对象时,SwiftData 会处理这些关系。默认使用.nullify删除规则,或者根据设置的.cascade 规则进行级联删除,例如,删除学校会删除所有学生,删除学生又会删除他们的考试结果。

清空数据库

如果你想删除并销毁所有 SwiftData 对象—即特定容器中每个模型的每个实例—你可能会认为应该调用ModelContainerdeleteAllData()。然而,从iOS 17.0开始,这个方法并没有用处:调用成功后,SwiftData 只与底层数据存储断开连接,数据并未改变,下次创建相同容器时数据会恢复。

再次强调,deleteAllData() 并不会按你期望的方式工作。

相反,你需要对每种模型类型调用模型上下文的 delete(model:) 方法,且不提供限制删除对象的谓词。例如,对于 CountryCity 模型,可以这样操作:

do {
    try modelContext.delete(model: Country.self)
    try modelContext.delete(model: City.self)
} catch {
    print("清除所有 Country 和 City 数据失败。")
}

需要注意的是,这并不意味着完全重置模型容器:所有的表定义和其他数据仍将保留,唯一变化的是数据将变为空。以下示例确保删除和保存操作得到了正确执行:

let result = try? context.fetch(FetchDescriptor<Country>())
if let oldResult = result {
    for data in oldResult {
        context.delete(data)
    }
    try? context.save()
}

根据时间删除示例

删除超过一天前创建的数据

let calendar = Calendar.current
var dateAgo: Date = calendar.date(
    byAdding: .day, value: -1, to: Date()
)!
try? context.delete(model: School.self, where: #Predicate { data in
    data.createAt < dateAgo
})

超过一个月前创建的时间

var dateAgo: Date = calendar.date(
    byAdding: .day, value: -7, to: Date()
)!

超过一个月前创建的时间

var dateAgo: Date = calendar.date(
    byAdding: .month, value: -1, to: Date()
)!

超过一季度前创建的时间

var dateAgo: Date = calendar.date(
    byAdding: .month, value: -3, to: Date()
)!

超过半年前创建的时间

var dateAgo: Date = calendar.date(
    byAdding: .month, value: -6, to: Date()
)!

超过一年前创建的时间

var dateAgo: Date = calendar.date(
    byAdding: .year, value: -1, to: Date()
)!
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容