如果我在源存储和目标存储之间有一些映射,则自动核心数据迁移?

时间:2015-02-08 20:20:21

标签: ios core-data core-data-migration

假设我有模型版本A存储,应用程序在AppStore中发布。 然后我添加了新的模型版本B,更新了一些实体(添加了一些转换旧属性的新属性),添加了映射模型,我在其中设置了新属性的值表达式,如FUNCTION($entityPolicy, "convertOldToNew:" , $source)并设置了适当的NSEntityMigrationPolicy子类名称(convertOldToNew:已实现)。

稍后我添加了新的模型版本C,其中包含新的转换规则(从B到C的新映射,新的NSEntityMigrationPolicy子类)。

当我设置NSPersistentStoreCoordinater时,我使用选项:

@{NSMigratePersistentStoresAutomaticallyOption:@YES,NSInferMappingModelAutomaticallyOption:@YES}. 

迁移有效,如果在每次应用程序更新后更新存储(当发布模型B的应用程序时,所有用户都会更新它并启动迁移;发布模型C时,所有用户都应该拥有带有B版本存储的应用程序)。但是,如果app已存储版本A,并且已更新为版本C,则迁移不起作用。我认为CoreData可以处理从版本到版本的所有可用映射,但它没有这样做。

我的问题是,我该如何处理这个案子?当我发布新的模型版本时,我是否应该添加映射以支持所有以前的版本(如果我有1到5的版本,我将有10个不同的映射)?

1 个答案:

答案 0 :(得分:0)

我是这样做的:

1)如果需要迁移

+ (NSDictionary *)metadataForPersistentStoreOfType:(NSString *)storeType URL:(NSURL *)url error:(NSError **)error    
- (BOOL)isConfiguration:(NSString *)configuration compatibleWithStoreMetadata:(NSDictionary *)metadata   

我将原始商店(sqlite,sqlite-wal,sqlite-shm)复制到临时文件。

2)开始迁移循环。我得到NSManagedObjectModel当前商店(在临时文件中),从其" versionIdentifiers"中读取下一个版本名称。 property,create next version object NSManagedObjectModel,load mapping:

+ (NSMappingModel *)mappingModelFromBundles:(NSArray *)bundles forSourceModel:(NSManagedObjectModel *)sourceModel destinationModel:(NSManagedObjectModel *)destinationModel

如果找不到映射,请尝试生成映射:

+ (NSMappingModel *)inferredMappingModelForSourceModel:(NSManagedObjectModel *)sourceModel destinationModel:(NSManagedObjectModel *)destinationModel error:(NSError **)error

并在迁移管理器中使用它:

- (instancetype)initWithSourceModel:(NSManagedObjectModel *)sourceModel destinationModel:(NSManagedObjectModel *)destinationModel
- (BOOL)migrateStoreFromURL:(NSURL *)sourceURL type:(NSString *)sStoreType options:(NSDictionary *)sOptions withMappingModel:(NSMappingModel *)mappings toDestinationURL:(NSURL *)dURL destinationType:(NSString *)dStoreType destinationOptions:(NSDictionary *)dOptions error:(NSError **)error

在每次迭代中,我删除以前的临时存储并开始使用新的临时存储。当找不到下一个NSManagedObjectModel时,我会停止循环并用最新的临时商店替换原始商店(与最新的NSManagedObjectModel版本兼容)。

在Xcode的每个NSManagedObjectModel版本中,我在versionIdentifiers属性中设置上一个和下一个版本信息,因此我可以在运行时加载适当的模型对象