Core Data托管对象模型的迁移
来自: https://segmentfault.com/a/1190000004506652
修改托管对象模型
在应用程序的进行过程中,其托管对象模型也可能需要进行修改。对于一些比较简单的修改,诸如设定属性的默认值、设定验证规则、使用获取请求模板等,是可以直接实施的。而对于另外一些更为结构化的修改,则需要把持久化存储区迁移到新的模型版本才行。假如没有提供迁移数据所需要的映射与设定,那么应用程序就会崩溃。
引发模型不兼容错误
在托管对象模型中添加另外一个新的实体,并且在新的实体中添加一些新的属性。重新运行应用程序,你会发现程序会崩溃掉。
对于处在开发初期的应用程序来说,这种崩溃算不上什么大的问题,我们只需要吧程序删除了并重新运行一次就好了。删除之后,在次运行应用程序时,它会按照最新的模型来创建持久化存储区。这样一来,存储区就可以和模型相兼容了,于是应用程序也就不会再次崩溃了。但是,这样做也会失去存储区里原有的数据。对于已经在 App Store 上架的程序来说,这让人无法接受。有好几种办法都可以迁移现有的持久化存储区,而迁移路径则是由变更的复杂程度以及是否使用 iCloud 等因素来决定的。无论采用哪种迁移办法,我们都必须首先熟悉“ 模型版本控制 ”。
添加模型版本
按照以下步骤来添加模型版本:
1、选中 Model.xcdatamodeld
2、点击Editor> Add Model Version... 菜单项
3、点击Finish,将Model2用作版本名称。
现在项目中会有两个版本的模型了。如图:
Model2.xcdatamodel这个新的模型的内容一开始便与 Model.xcdatamodel 完全相同。
我们现在选中 Model2.xcdatamodel 这个新的模型,在这个新的模型中添加 Measurement 实体,创建名叫abc的属性,并将其类型设置为String。
添加了新的版本模型之后,必须将其设置为当前版本,然后才能让应用程序使用它。
选中 Model.xcdatamodeld 在右侧将 Current Model Version 设置为Model2.如图:
如果想正常运行应用程序,那么我们还需要配置好迁移选项,告诉Core Data应该如何去迁移。要是现在就去运行应用程序的话,那自然还是会发生Store is incompatible(存储区不兼容)错误。
轻量级的迁移方式
把新的模型设置为当前版本之后,必须迁移现有的持久化存储区,只有这样,才能正常使用新模型。这是因为,持久化存储区协调器会试着使用新的模型来打开原有的存储区,但是原有的存储区是用旧版本的模型创建的,所以会出现错误。在向 NSPersistentStoreCoordinator 添加存储区的时候,只需要将下列选项放在 NSDictionary 里面传过去,即可自动完成存储区的迁移工作:
如果传给 NSPersistentStoreCoordinator 的 NSMigratePersistenStoresAutomaticallyOption 是 YES ,那么Core Data 就会试着把低版本的持久化存储区迁移到最新版本的模型。
如果传给 NSPersistentStoreCoordinator 的 NSInferMappingModelAutomaticallyOption 是YES,那么Core Data 就会试着以最为合理地方式自动推断出源模型实体中的某个属性到底对应于“目标模型实体”中的哪一个属性。
打开 CoreDataHelper.swift 同时添加一个属性在这个类中。
lazy var options: NSDictionary?
Right now, you’re setting up the persistent store with no options for default behavior. You’ll use the options dictionary to set the necessary flags.
// 这里是添加的部分,名如其意,当我们需要自动版本迁移时,我们需要在addPersistentStoreWithType方法中设置如下options let options = [NSInferMappingModelAutomaticallyOption: true, NSMigratePersistentStoresAutomaticallyOption: true] var error: NSError? = nil persistentStoreCoordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: options, error: &error)