核心数据版本控制和使用自定义策略迁移

我发现文档非常有限,我的问题解决方案无处可寻。

我需要添加新实体(与现有实体的关系)。 还添加并重命名现有实体的一些属性。

轻量化的例子:

旧模型具有一个具有一个属性name实体Item

在新模型中,我希望Item具有一个新属性dateAdded并将namenametitle 。 此时,如果dateAdded是可选的或给定默认值,我可以使用轻量级迁移function。 如果我错了,请纠正我。

但我还想添加带有title属性的新List实体。 并添加许多关系。 列表可以为空或有很多项目。 项目必须完全引用一个列表。

所以我很困惑我要做的一切和订单。

  1. 禁用轻量级迁移function打开迁移( NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:NO], NSInferMappingModelAutomaticallyOption, nil]; )。

  2. 创建新版本的模型。 在那里,我做了我想做的改变。

  3. 创建一个新的映射模型。 来源是旧模型,目标是新模型。 在ItemToItem我将title设置为$source.name

除了Xcode在使用映射模型时仍然崩溃我不知道接下来该做什么。 我想我必须在上下文中创建一个List实例,并根据关系策略使所有项引用它。 我应该使用自定义NSEntityMigrationPolicy来执行此操作。 有任何帮助来完成这一挑战吗?

好吧,我做到了……

我的前3个步骤是正确的。 继续方案:

ADD4。 执行ItemToItemMigrationPolicyItemToItemMigrationPolicy的子类。 覆盖:

 - (BOOL)beginEntityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error { List* list = (List*)[NSEntityDescription insertNewObjectForEntityForName:@"List" inManagedObjectContext:[manager destinationContext]]; list.name = @"Default list"; return YES; } - (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error { Item* item = (Item*)[NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName] inManagedObjectContext:[manager destinationContext]]; item.dateAdded = [NSDate date]; task.title = [sInstance valueForKey:@"name"]; [manager associateSourceInstance:sInstance withDestinationInstance:item forEntityMapping:mapping]; return YES; } - (BOOL)createRelationshipsForDestinationInstance:(NSManagedObject *)dInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error { NSFetchRequest* fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"List"]; NSPredicate* predicate = [NSPredicate predicateWithFormat:@"name LIKE 'Default list'"]; fetchRequest.predicate = predicate; NSError* fetchRequestError = nil; NSArray* listsArray = [manager.destinationContext executeFetchRequest:fetchRequest error:&fetchRequestError]; if (fetchRequestError) { NSLog(@"%@", fetchRequestError.localizedDescription); } List* list = [listsArray lastObject]; ((Item*)dInstance).list = list; return YES; } 

ADD5。 在Xcode中,在映射模型中将ItemToItem迁移策略设置为自定义ItemToItemMigrationPolicy值。

ADD6。 使新模型版本成为当前版本并从新实体或已更改实体生成(替换)类。

ADD7。 您的代码中的更改,例如item.name不再有效。 现在是item.title 。 清理项目并运行。

如果要添加新实体,则需要使用自定义映射模型并关闭轻量级迁移。

一件重要的事情。 使用迁移时,请确保每次都使用现有持久性存储的新示例,尤其是在发生崩溃时。 如果你不这样做,你可以破坏商店,这会导致错误滚雪球。

Interesting Posts