概述
在 WWDC 24 中,苹果推出了数据库框架 SwiftData 2.0 版本。其新加入的历史记录追踪(History Trace)机制着实让秃头码农们“如痴如醉”了一番。
我们在之前的博文中已经介绍了 History Trace 是如何处理数据新增操作的。而在这里,我们将再接再厉来完成数据删除时的全盘考量。
在本篇博文中,您将学到如下内容:
- 概述
- 9. SwiftData 对于托管对象删除的稳妥处理
- 总结
这是本系列第五篇博文。闲言少叙,让我们马上开始 SwiftData 精彩的探究之旅吧!
Let‘s dive in!!!😉
9. SwiftData 对于托管对象删除的稳妥处理
在之前的博文中,我们讨论过如何利用历史记录追踪机制(History Trace)来处理后台线程中记录的插入操作。
我们已然知晓:History Trace 可以监听 3 种类型的数据改变:新增、更新和删除。
其中更新和新增的情况比较类似,我们不再赘述。
这里,让我们“集中火力”来聊聊 History Trace 中关于记录删除时的处理。
当托管对象从 SwiftData 持久数据库中删除时,我们仍然可以通过其实例中的 persistentModelID 来“招魂”。但是,对它任意字段的所有访问将会立即导致应用崩溃。
为了能让大家体会到这种情况,我们将之前 ContentView 视图的代码略作如下修改:
struct ContentView: View {
@Environment(\.modelContext) var modelContext
@Query var items: [Item]
private func handleChangeInMainContext() {
let mainContext = modelContext
var historyDesc = HistoryDescriptor<DefaultHistoryTransaction>()
historyDesc.predicate = #Predicate {
trans in
trans.author == "BG"
}
let transactions = try! mainContext.fetchHistory(historyDesc)
for trans in transactions {
for change in trans.changes {
// 在删除后,下面这个 changedItem 其实已是“尸体”💀
guard let changedItem = mainContext.model(for: change.changedPersistentIdentifier) as? Item else {
continue }
// 试图访问已删除对象中任何字段的内容都会导致崩溃
switch change {
case .insert(_)