更新1
有关local store和cloud store的补充说明。
苹果文档讲述了Core Data融合的基本的方法。不过,它讲述的比较简略。代码好多部分都是占位符,需要自己填写。此外,苹果的融合,默认的单机模式,也就是没有使用CloudKit的同步的情况。如果你使用CloudKit,就会遇到苹果没有提到的情况。
融合升级的步骤
融合升级的基本步骤:
- 融合
- 打开新数据库
不过我更建议:
- 查询是否能够融合
- 融合
- 打开新数据库
下面的文章基于后者。
1. 查询是否能够融合
private func canMigration() -> Bool {
let sourceURL = Bundle.main.url(forResource: "Model", withExtension: "mom", subdirectory: "Model.momd")
let destinationURL = Bundle.main.url(forResource: "Model 2", withExtension: "mom", subdirectory: "Model.momd")
let sourceModel = NSManagedObjectModel(contentsOf: sourceURL!)
let destinationModel = NSManagedObjectModel(contentsOf: destinationURL!)
if let _ = try? NSMappingModel.inferredMappingModel(forSourceModel: sourceModel!, destinationModel: destinationModel!) {
return true
}
return false
}
注意:在Xcode中,创建模型的文件扩展名分别是“xcdatamodeld”和“xcdatamodel”,但是生成应用之后,它们的扩展名变成了“momd”和“mom”,并且前者变成了独立的文件夹。
这一步的作用是,提前知晓能否转换。如果这一步都不成,就不用执行下一步了。如果直接执行下一步,那么两部的错误可能会同时呈现,增加调试的难度。
2. 融合
private func migragtionFromModel2Model2() {
let container = NSPersistentContainer(name: "Model")
let moc = container.viewContext
let applicationSupportFolderURL = try? FileManager.default.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
#if targetEnvironment(macCatalyst)
let storeURL = URL(fileURLWithPath: "Photo Organizer/Model.sqlite", isDirectory: false, relativeTo: applicationSupportFolderURL)
#else
let storeURL = URL(fileURLWithPath: "Model.sqlite", isDirectory: false, relativeTo: applicationSupportFolderURL)
#endif
let options:Dictionary<AnyHashable, Any>? = [
NSMigratePersistentStoresAutomaticallyOption : NSNumber(value: true),
NSInferMappingModelAutomaticallyOption: NSNumber(value: true),
NSPersistentHistoryTrackingKey: NSNumber(value: true)
]
if let _ = try? moc.persistentStoreCoordinator!.addPersistentStore(type: NSPersistentStore.StoreType.sqlite, configuration: "Local", at: storeURL, options: options) {
print("success")
} else {
print("failed")
}
}
此处需要注意两点:
- macCatalyst下的sqlite位置与iOS不同,前面多了一个应用名。(行11到15)
- 如果你之前使用过CloudKit同步,那么还需要多一个“ NSPersistentHistoryTrackingKey: NSNumber(value: true)”。(行20)否则数据库就会以只读方式打开,无法同步。
3. 打开新数据库
这个就是融合升级之前打开的方式。值得一提的是,如果你融合升级之后,还想要对于数据库的内容进行额外的处理。那么应该在这一步完成之后,进行处理。