第 2 章:创建第一个 SwiftData 应用
使用 ModelContext 进行数据的增删改查 (CRUD)
ModelContext 是 SwiftData 中管理数据操作的核心组件,负责处理对象的创建、读取、更新和删除(CRUD)。本节将详细介绍如何使用 ModelContext 实现完整的 CRUD 操作。
1. 创建对象 (insert)
// 1. 创建模型实例
let newTask = Task(title: "完成SwiftData学习", isCompleted: false)
// 2. 通过ModelContext插入对象
modelContext.insert(newTask)
// 3. 保存更改(可选,取决于是否启用自动保存)
try? modelContext.save()
关键点:
- 直接实例化
@Model修饰的类 - 必须调用
insert()方法将对象纳入管理 - 保存操作可以是手动的,也可以通过配置自动完成
2. 读取对象 (fetch 和 @Query)
方式一:命令式查询 (fetch)
// 创建FetchDescriptor
let descriptor = FetchDescriptor<Task>(
predicate: #Predicate { $0.isCompleted == false },
sortBy: [SortDescriptor(\.createdAt, order: .forward)]
)
// 执行查询
let pendingTasks = try? modelContext.fetch(descriptor)
方式二:声明式查询 (@Query)
// 在SwiftUI视图中使用
struct TaskListView: View {
@Query(sort: \.createdAt) var tasks: [Task]
var body: some View {
List(tasks) { task in
Text(task.title)
}
}
}
谓词示例:
// 复杂谓词构建
#Predicate<Task> { task in
(task.priority == .high || task.dueDate < Date())
&& !task.isCompleted
}
3. 更新对象
// 1. 获取对象(通过fetch或@Query)
guard let task = tasks.first else { return }
// 2. 直接修改属性(自动标记为脏数据)
task.isCompleted = true
task.completedAt = Date()
// 3. 保存更改(如果未启用自动保存)
try? modelContext.save()
特点:
- 修改已托管对象的属性会自动触发变更跟踪
- 不需要显式调用更新方法
4. 删除对象 (delete)
// 1. 获取要删除的对象
let taskToDelete = tasks[0]
// 2. 调用delete方法
modelContext.delete(taskToDelete)
// 3. 保存更改
try? modelContext.save()
删除规则:
- 受
@Relationship的删除规则约束(Cascade/Nullify/Deny) - 删除操作会立即从上下文中移除对象
5. 保存策略
| 方式 | 配置方法 | 特点 |
|---|---|---|
| 自动保存 | ModelContainer(autoSave: true) | 每次变更自动持久化 |
| 手动保存 | ModelContainer(autoSave: false) | 需显式调用 save() |
| 事务保存 | modelContext.transaction { ... } | 批量操作的原子性 |
最佳实践:
// 批量操作使用transaction
try modelContext.transaction {
for task in expiredTasks {
task.status = .archived
}
try modelContext.save()
}
调试技巧
// 打印上下文状态
print("Has changes: \(modelContext.hasChanges)")
// 查看待处理变更
modelContext.registeredModels.forEach { object in
print("Object: \(object), status: \(modelContext.getStatus(for: object))")
}
注意:所有持久化操作都可能抛出错误,生产代码应该实现完整的错误处理逻辑。
