第6章:Schema 和版本迁移
版本控制与数据模型的演进
1. 数据模型版本化的必要性
在应用的生命周期中,数据模型会随着需求变化而演进。版本控制允许你:
- 保留旧数据模型的兼容性
- 支持增量式功能迭代
- 确保用户数据在升级时不会丢失
2. 创建模型版本
在Xcode中操作步骤:
- 选择
.xcdatamodeld文件 - 点击菜单栏
Editor > Add Model Version... - 输入新版本名称(如
MyAppModelV2) - 选择基于哪个旧版本创建
// 配置ModelContainer时指定版本
let container = try ModelContainer(
for: MyAppModelV2.self,
migrationPlan: MyMigrationPlan.self
)
3. 迁移策略选择
| 策略类型 | 适用场景 | 特点 |
|---|---|---|
| 自动轻量级迁移 | 简单属性变更 | 系统自动处理 |
| 自定义迁移 | 复杂结构变化 | 需要实现SchemaMigrationPlan |
| 手动迁移 | 极端特殊情况 | 完全控制迁移过程 |
4. 实现自定义迁移计划
enum MyMigrationPlan: SchemaMigrationPlan {
static var schemas: [VersionedSchema.Type] = [
MyAppModelV1.self,
MyAppModelV2.self
]
static var stages: [MigrationStage] = [
// 第一阶段迁移
migrateV1toV2
]
static let migrateV1toV2 = MigrationStage.custom(
fromVersion: MyAppModelV1.self,
toVersion: MyAppModelV2.self,
willMigrate: { context in
// 迁移前准备
},
didMigrate: { context in
// 迁移后处理
}
)
}
5. 测试迁移流程
关键测试要点:
- 使用旧版本应用生成测试数据
- 升级到新版本验证数据完整性
- 测试回滚场景(如迁移失败时)
// 测试代码示例
func testMigration() throws {
let oldStoreURL = // 旧版本数据库路径
let config = ModelConfiguration(url: oldStoreURL)
let container = try ModelContainer(
for: CurrentModel.self,
configurations: config
)
// 验证迁移后数据
}
6. 版本演进的最佳实践
- 增量修改:每次只做最小必要变更
- 保留旧版本:至少保留最近2-3个旧版本
- 文档记录:记录每个版本的变更内容
- 兼容性考虑:确保新版本能处理旧数据
- 用户通知:重大变更时提供升级说明
7. 常见问题解决方案
问题1:迁移后属性值为nil
- 检查是否在模型中正确设置了默认值
- 验证
didMigrate闭包中是否漏掉数据处理
问题2:迁移性能差
- 对大数据库分批处理迁移
- 考虑在后台线程执行迁移
问题3:测试覆盖率不足
- 为每个迁移路径编写测试用例
- 包含边界情况测试(如空数据库迁移)
