迁移到 SwiftData
Migrate to SwiftData
2023年6月5日
一句话判断
Core Data 到 SwiftData 的迁移有两条路径——完全迁移(删掉 Core Data 栈,全面拥抱 SwiftData)和共存模式(两个栈共享同一个持久化存储,渐进式迁移),Xcode 的 Managed Object Model Editor 助手可以自动生成 SwiftData 模型类。
这场 Session 讲了什么
Luvena 详细介绍了从 Core Data 迁移到 SwiftData 的三种场景。
自动生成 SwiftData 模型类:使用 Xcode 的 Managed Object Model Editor 助手(Editor > Create SwiftData Code),可以从现有的 Core Data 模型文件自动生成对应的 SwiftData 模型类。生成的类包含实体属性和关系的完整映射。
完全迁移:删除 Core Data 的 Managed Object Model 文件和 Persistence 文件,替换为 SwiftData 的 ModelContainer 和 @Query。关键约束是 SwiftData 模型中实体名称和属性必须与 Core Data 中的完全匹配,这样才能正确读取现有数据。SwiftData 的隐式保存机制替代了 Core Data 的手动 save 调用。
共存模式:Core Data 和 SwiftData 使用两个完全独立的持久化栈,但指向同一个存储文件。这允许渐进式迁移——不需要一次性重写所有代码。前提条件是必须开启持久化历史追踪(Persistent History Tracking),否则存储会被设为只读模式。SwiftData 自动开启此功能,但 Core Data 需要手动配置。
值得深挖的点
Schema 匹配的严格性:完全迁移时,SwiftData 模型的实体名称和属性名必须与 Core Data 中的完全一致。任何不匹配都会导致数据无法正确读取。迁移前需要彻底测试所有模型。
共存模式的双栈设计:两个栈完全独立运行,通过同一个 SQLite 文件通信。Persistent History Tracking 是关键的同步机制——它记录所有变更历史,让另一个栈能感知到对方做的修改。
隐式保存的工作时机:SwiftData 在 UI 生命周期事件和定时器触发时自动保存。你不再需要手动调用 save(),但你仍然可以显式调用 modelContext.save() 来强制保存。
向后兼容的考虑:SwiftData 仅支持 iOS 17+ 和 macOS Sonoma+。如果你的应用还需要支持旧系统,共存模式是唯一选择——在旧系统上用 Core Data,在新系统上用 SwiftData。
代码片段
// 完全迁移 - 设置 SwiftData 栈
@main
struct SampleTripsApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
// 替代 Core Data 的 NSPersistentContainer
.modelContainer(for: [Trip.self, LivingAccommodation.self, BucketListItem.self])
}
}
// 完全迁移 - 对象创建的对比
// Core Data 方式
let trip = Trip(context: managedObjectContext)
trip.name = "Paris"
trip.destination = "France"
try managedObjectContext.save() // 手动保存
// SwiftData 方式 - 更简洁
let trip = Trip(name: "Paris", destination: "France")
modelContext.insert(trip)
// 不需要手动 save() - 隐式保存自动处理
// 完全迁移 - 数据查询的对比
// Core Data 方式
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Trip.startDate, ascending: true)]
)
var trips: FetchedResults<Trip>
// SwiftData 方式
@Query(sort: \Trip.startDate, order: .forward)
var trips: [Trip]
// 共存模式 - 配置 Core Data 栈指向同一存储
let storeURL = URL.storeURL(for: "MyApp", databaseName: "SharedStore")
let description = NSPersistentStoreDescription(url: storeURL)
// 必须开启持久化历史追踪
description.setOption(true as NSNumber,
forKey: NSPersistentHistoryTrackingKey)
container.persistentStoreDescriptions = [description]
最佳实践
- 用 Xcode 助手生成模型类:不要手写迁移代码,用 Editor > Create SwiftData Code 自动生成,确保属性映射正确。
- 完全迁移前彻底测试 Schema 匹配:每个实体的名称和属性都必须精确匹配,遗漏一个就会导致数据丢失。
- 共存模式必须开启 Persistent History Tracking:否则存储进入只读模式,两个栈都无法写入。
- 共存模式适合渐进式迁移:先在新功能中使用 SwiftData,旧代码继续用 Core Data,逐步替换。
- 考虑最低支持版本:如果需要支持 iOS 16 及更早版本,只能用共存模式。
还有什么值得关注
- 共存模式为大型应用提供了现实的迁移路径——不需要一次性重写所有数据层代码。
- SwiftData 的隐式保存大幅减少了样板代码,但也意味着你需要信任系统的保存时机。
- Session 中的 SampleTrips 应用是一个很好的参考项目,展示了 Trip、LivingAccommodation 和 BucketListItem 三个实体之间的完整关系映射。