Highlight
SwiftData 可以和 Core Data 共存于同一个应用,开发者既可以用 Xcode 助手一键生成 SwiftData 模型类完成完全迁移,也可以让两个持久化栈共享同一个存储文件实现渐进式过渡,无需一次性重写所有代码。
核心内容
很多应用已经用 Core Data 跑了多年,数据模型复杂、代码量庞大。WWDC23 推出 SwiftData 后,这些应用的开发者面临一个实际问题:要不要迁移?怎么迁移?
这个 session 给出了三种方案:完全迁移、共存模式、以及从 Xcode 自动生成模型类的快捷入口。核心思路是灵活——根据你的团队资源、版本兼容需求、代码复杂度来选择最适合的路径。
自动生成 SwiftData 模型类
(01:05)如果你已有 Core Data 的 .xcdatamodeld 文件,Xcode 可以帮你自动生成对应的 SwiftData 模型类。
操作步骤:
- 在 Xcode 中选中模型文件
- 菜单栏选择 Editor > Create SwiftData Code
- 为每个实体生成对应的 Swift 文件
生成的 SwiftData 模型长这样:
import SwiftData
@Model
class Trip {
var name: String
var destination: String
var startDate: Date
var endDate: Date
var livingAccommodation: LivingAccommodation?
var bucketList: [BucketListItem]?
}
关键点:
- 生成的类自动加上
@Model宏 - 属性和关系与 Core Data 实体一一对应
- 如果从头新建 SwiftData 应用,不需要这个助手,直接写
@Model类即可
完全迁移
(03:09)完全迁移意味着删除 Core Data 的所有痕迹,用 SwiftData 替代。
迁移前的检查清单:
- 每个 Core Data 实体必须有对应的 SwiftData 模型类
- 实体名称必须完全匹配
- 所有属性和关系必须在 SwiftData 中都有对应定义
- 确认所有 Core Data 特性在 SwiftData 中都受支持
迁移步骤:
- 用 Xcode 助手生成 SwiftData 模型类
- 删除
.xcdatamodeld文件 - 删除原来的 Persistence 文件(设置 Core Data stack 的代码)
- 用
.modelContainer()设置 SwiftData stack
(04:37)SwiftUI 中设置 ModelContainer:
@main
struct TripsApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(
for: [Trip.self, BucketListItem.self, LivingAccommodation.self]
)
}
}
关键点:
.modelContainer()同时创建 container 和 context- Context 自动注入到 SwiftUI 环境中
- 不需要手动管理 NSPersistentContainer
(04:57)对象创建的对比:
Core Data 方式:
@Environment(\.managedObjectContext) private var viewContext
let newTrip = Trip(context: viewContext)
newTrip.name = name
newTrip.destination = destination
newTrip.startDate = startDate
newTrip.endDate = endDate
SwiftData 方式:
@Environment(\.modelContext) private var modelContext
let trip = Trip(
name: name,
destination: destination,
startDate: startDate,
endDate: endDate
)
modelContext.insert(object: trip)
关键点:
- SwiftData 用普通初始化器创建对象,不需要传 context
- 创建后调用
insert()标记为需要持久化 - 代码更简洁,类型更安全
(05:51)保存机制也有变化。SwiftData 支持隐式保存:
- UI 生命周期事件触发保存
- Context 变更后定时自动保存
- 可以移除 Core Data 中显式调用
save()的代码
(06:16)数据获取从 FetchRequest 变为 @Query:
@Query(sort: \.startDate, order: .forward)
var trips: [Trip]
关键点:
@Query直接返回[Trip],不需要包装成FetchedResults- 支持排序和 predicate
- 自动响应数据变化刷新 UI
共存模式
(06:51)完全迁移不总是可行。如果你的应用需要支持 iOS 16 及以下版本,或者代码量太大无法一次性重写,共存模式是更好的选择。
共存模式让 Core Data 和 SwiftData 两个独立的持久化栈指向同一个存储文件。你可以在旧代码中继续用 Core Data,在新功能中使用 SwiftData。
(07:30)设置共存的关键配置:
let url = URL(fileURLWithPath: "/path/to/Trips.store")
if let description = container.persistentStoreDescriptions.first {
description.url = url
description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
}
关键点:
- 两个 stack 必须指向同一个存储 URL
- 必须开启 Persistent History Tracking
- SwiftData 自动开启此功能,Core Data 需要手动设置
- 如果不开启,存储会被设为只读模式
(08:51)类名冲突的处理:
// Core Data 类
class CDTrip: NSManagedObject {
// ...
}
// SwiftData 类
@Model final class Trip {
// ...
}
关键点:
- Core Data 和 SwiftData 的类不能同名
- 可以给 Core Data 类加前缀(如 CDTrip)
- 类名改了,但实体名保持不变
- 也可以在 Managed Object Model Editor 中修改类名
共存模式的其他要求:
- 两个 schema 必须保持同步,不能分叉
- 新增属性和关系必须以相同方式添加到两个模型中
- 实体版本哈希必须匹配,否则会触发意外迁移
- 多版本 schema 需要正确管理版本差异
UIKit / AppKit 应用怎么办
(10:25)SwiftData 虽然和 SwiftUI 深度集成,但 UIKit 和 AppKit 应用也能用:
- 共存方案:UIKit 代码继续绑定 Core Data,SwiftData 在并行的新功能中使用
- 包装方案:把 SwiftData 类当作普通 Swift 类,用 UIKit 代码包装使用
详细内容
迁移决策树
选择哪种迁移策略,取决于几个因素:
| 因素 | 完全迁移 | 共存模式 |
|---|---|---|
| 最低支持版本 | iOS 17+ | iOS 16 或更早 |
| 代码重写成本 | 高(一次性) | 低(渐进式) |
| 团队资源 | 充足 | 有限 |
| 数据模型复杂度 | 简单到中等 | 复杂 |
| 长期维护 | 更简洁 | 需要维护两套代码 |
Schema 兼容性检查
迁移前必须验证:
- 实体名称:Core Data 实体名 == SwiftData 类名
- 属性名称和类型:完全匹配
- 关系:双向关系在 SwiftData 中用
@Relationship标注 - 约束:如唯一性约束用
@Attribute(.unique) - 不受支持的特性:如 fetched properties、fetch requests 等
版本管理
共存模式下,schema 变更需要同时更新两个模型:
- 在 Core Data 的
.xcdatamodeld中添加新属性 - 在 SwiftData 的
@Model类中添加对应属性 - 确保两个模型的实体版本哈希一致
- 使用 versioned schema 管理 SwiftData 模型版本
核心启发
1. 给现有 Core Data 应用逐步引入 SwiftData
- 做什么:不改动旧功能,在新模块中使用 SwiftData,通过共存模式共享数据
- 为什么值得做:零风险尝试 SwiftData,团队可以边学边用,不需要大规模重构
- 怎么开始:配置共存 stack,给 Core Data 类加前缀避免命名冲突,在新功能中使用
@Query和@Model
2. 用 Xcode 助手快速生成 SwiftData 模型
- 做什么:几分钟内把现有的
.xcdatamodeld转换成 SwiftData 类 - 为什么值得做:避免手写映射错误,自动保持属性名和类型一致
- 怎么开始:选中模型文件 > Editor > Create SwiftData Code,检查生成的类是否符合预期
3. 做一个跨版本的笔记应用
- 做什么:支持 iOS 16 和 iOS 17+ 的笔记应用,iOS 16 用 Core Data,iOS 17 用 SwiftData
- 为什么值得做:共存模式让同一个存储文件被两个 stack 访问,用户数据无缝过渡
- 怎么开始:运行时判断系统版本,选择初始化 Core Data stack 或 SwiftData stack,共享同一个存储 URL
4. 重构遗留的 Core Data 代码
- 做什么:把臃肿的 Core Data 代码逐步替换成 SwiftData
- 为什么值得做:减少样板代码,获得类型安全和更好的 SwiftUI 集成
- 怎么开始:从最简单的实体开始迁移,验证数据一致性后逐步扩大范围,用
@Query替换FetchRequest
关联 Session
- Meet SwiftData — SwiftData 的入门介绍,包含基础概念和 API 使用
- Model your schema with SwiftData — 深入了解 SwiftData 的数据建模,包括 versioned schema
- Dive deeper into SwiftData — SwiftData 的高级用法和性能优化
- Build an app with SwiftData — 从零开始用 SwiftData 构建完整应用
评论
GitHub Issues · utterances