swift - 迁移以更改 CoreData 的配置
问题描述
我使用 CoreData 的默认配置启动了一个 macOS 项目。应用程序已发布,一些用户开始使用它。现在,我需要一些数据与 iCloud 同步,一些数据只存储在本地。如果我理解正确,我能做到这一点的唯一方法是创建两个不同的配置(在 CoreData 数据模型中),在每个配置中添加所需的实体,并相应地配置 NSPersistentContainer。但是,上述方法可能会导致一些数据丢失,因为我将不再使用默认配置。
有什么方法可以将默认配置下保存的数据“迁移”到另一个配置?
解决方案
经过反复试验,我找到了一个似乎可以完成工作的解决方案(但是,它似乎很脏)。首先,在实例化容器时,我确保将我的 3 个 storeDescriptors 添加到persistentStoreDescriptions
(每个代表一个方案)
let defaultDirectoryURL = NSPersistentContainer.defaultDirectoryURL()
var persistentStoreDescriptions: [NSPersistentStoreDescription] = []
let localStoreLocation = defaultDirectoryURL.appendingPathComponent("Local.sqlite")
let localStoreDescription = NSPersistentStoreDescription(url: localStoreLocation)
localStoreDescription.cloudKitContainerOptions = nil
localStoreDescription.configuration = "Local"
persistentStoreDescriptions.append(localStoreDescription)
let cloudStoreLocation = defaultDirectoryURL.appendingPathComponent("Cloud.sqlite")
let cloudStoreDescription = NSPersistentStoreDescription(url: cloudStoreLocation)
cloudStoreDescription.configuration = "iCloud"
cloudStoreDescription.cloudKitContainerOptions = "iCloud.com.xxx.yyy"
persistentStoreDescriptions.append(cloudStoreDescription)
let defaultStoreLocation = defaultDirectoryURL.appendingPathComponent("Default.sqlite")
let defaultStoreDescription = NSPersistentStoreDescription(url: defaultStoreLocation)
defaultStoreDescription.cloudKitContainerOptions = nil
defaultStoreDescription.configuration = "Default"
persistentStoreDescriptions.append(defaultStoreDescription)
container.persistentStoreDescriptions = persistentStoreDescriptions
注意:一件重要的事情是确保最后NSPersistentStoreDescription
添加 默认配置。
其次,我认为所有保存在核心数据中的数据检查是否managedObject.objectID.persistentStore?.configurationName
是"Default"
(或任何包含默认值的字符串。通过我的经验实现,我得出的结论是配置名称可能因情况而异)。如果上述条件为真,则新建一个managedObject,我将旧的所有属性复制到新的,删除旧的托管对象,并保存上下文。
for oldManagedObject in managedObjectRepository.getAll() {
guard let configurationName = oldManagedObject.objectID.persistentStore?.configurationName else {
continue
}
if (configurationName == "Default") {
let newManagedObject = managedObjectRepository.newManagedObject()
newManagedObject.uuid = oldManagedObject.uuid
newManagedObject.createDate = oldManagedObject.createDate
......
managedObjectRepository.delete(item: oldManagedObject)
managedObjectRepository.saveContext()
}
}
通过此实现,以前保存的旧数据Default.sqlite
现在保存在Local.sqlite
“Cloud.sqlite”中(取决于哪个配置包含哪个实体)。
推荐阅读
- javascript - 如何将 Json 对象中的值显示到 Mat-Select 中
- mysql - 3个文本框1个数据查询mysql
- html - CSS:盒子柔性显示
- python-3.x - 将列表推导转换为嵌套循环会导致无限循环
- python - 我收到此错误:“fx 和 y 必须具有相同的第一维但具有 python 形状”
- javascript - 如何获得变量?
- r - 匹配来自 R 中两个不同数据帧的数据,如 Excel VLOOKUP
- r - 运行所有测试 R 包的测试?
- node.js - 如何强制我的函数在继续之前等待承诺?
- javascript - 如何检查用户是否具有来自另一个 Discord 服务器的角色