了解 SwiftData 模型定义、关联关系、容器与上下文配置、增删改查等,实现基本业务功能。
对于复杂应用场景,可查阅文档: https://www.hackingwithswift.com/quick-start/swiftdata/
模型定义
通过 File - New - Empty File 创建一个新文件
- 创建类,实现 Identifiable 协议,它的主要作用是为类型提供稳定的身份标识,必须提供一个 id 属性,用于唯一标识该类型的每个实例。
import SwiftData
并给类声明@Model
宏,定义它为 SwiftData 模型- 类需要 init 方法,在类中的某个地方键入 i,会自动生成 init 方法,可修改 init 方法的默认值
- 使用
@Attribute(.unique)
标记唯一标识符id - 定义一对多模型关联关系,引入其他 SwiftData 模型为数组。
比如创建一个 ProgressItem 进度事项模型:
import Foundation
import SwiftData
@Model
final class ProgressItem: Identifiable {
@Attribute(.unique) var id: UUID
var title: String
var itemDescription: String
var totalAmount: Double
var completedAmount: Double
var unit: String
var isCompleted: Bool
var isAbandoned: Bool
var createdDate: Date
var lastUpdated: Date
var progressRecords: [ProgressRecord]?
init(title: String, description: String, totalAmount: Double, unit: String) {
self.id = UUID()
self.title = title
self.itemDescription = description
self.totalAmount = totalAmount
self.completedAmount = 0.0
self.unit = unit
self.isCompleted = false
self.isAbandoned = false
self.createdDate = Date()
self.lastUpdated = Date()
self.progressRecords = []
}
}
ProgressRecord 进展记录模型:
import Foundation
import SwiftData
@Model
final class ProgressRecord: Identifiable {
@Attribute(.unique) var id: UUID
var amount: Double
var note: String?
var date: Date
init(amount: Double, note: String? = nil) {
self.id = UUID()
self.amount = amount
self.note = note
self.date = Date()
}
}
到 iTourApp.swift 也 import SwiftData
,并给 WindowGroup 添加此修饰符: .modelContainer(for: Destination.self)
数据查询
使用@Query
属性包装器来声明式地获取数据:
@Query private var progressItems: [ProgressItem]
@Query
可传 filter 参数对参数进行过滤:
@Query(filter: #Predicate<ProgressItem> { $0.isCompleted == true })
private var completedItems: [ProgressItem]
也可以在视图中过滤:
ForEach(progressItems.filter { !$0.isCompleted && !$0.isAbandoned })
模型容器与上下文
在 App 入口文件中配置共享的模型容器:
var sharedModelContainer: ModelContainer = {
let schema = Schema([
ProgressItem.self,
ProgressRecord.self,
])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
do {
return try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}()
通过 .modelContainer 修饰符提供模型上下文
在预览中:
#Preview {
ContentView().modelContainer(for: [ProgressItem.self, ProgressRecord.self])
}
在应用主体中:
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(sharedModelContainer)
}
在组件中获取 SwiftData 的模型上下文:
- modelContext 是数据操作的核心入口,用于管理实体对象的创建、查询、更新和删除
- 无需手动创建,通过 @Environment 自动从父视图继承,确保数据操作的一致性
@Environment(\.modelContext) private var modelContext
模型上下文用于插入新对象、删除对象和保存更改:
// 插入新对象
modelContext.insert(newItem)
// 删除对象
modelContext.delete(item)
// 保存更改
try modelContext.save()
增删改数据操作
插入数据 ,如创建新事项并插入:
let newItem = ProgressItem(title: title, description: description, totalAmount: totalAmountValue, unit: unit)
modelContext.insert(newItem)
更新数据,如更新事项属性并保存:
progressItem.completedAmount += amount
progressItem.lastUpdated = Date()
try modelContext.save()
删除数据 ,如删除事项:
modelContext.delete(item)
try modelContext.save()
处理迁移
如果 SwiftData 的模型结构发生了不兼容的更改,但本地已有旧的数据存储文件,会导致 SwiftData 无法加载。
开发阶段可删除模拟器/真机上的 App,清除数据,重新运行项目即可。
生产环境下,模型变更要用数据迁移,否则用户数据会丢失。
- 简单变更(如添加新属性、重命名属性等),可自动执行轻量级迁移。
- 当模型发生破坏性变更(删除属性、修改关系、类型变更等)时,需要自定义迁移计划,定义、创建和应用。