我已经想通了。首先,在创建持久存储协调器时设置这些选项:
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
nil];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil URL:storeURL options:options error:&error])
{
//other code handle error
}
使用 Xcode 创建映射模型,设置其源版本和目标版本。
创建一个 NSEntityMigrationPolicy 的子类,命名它MyPolicy
,覆盖方法。
-(BOOL)createRelationshipsForDestinationInstance:(NSManagedObject *)dInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error
调用此方法时,所有 managedObjects 都已在目标上下文中创建,但它们的关系不是。在此方法中,检查 dInstance 是什么实体,并为其建立关系。
使用 Xcode,在您的映射模型中,将 ENTITY MAAPPINGS 命名InstanceToInstance
的映射策略设置为MyPolicy
。
此方法将为每个 Instance 对象调用一次。对于我的问题,我应该这样做:
-(BOOL)createRelationshipsForDestinationInstance:(NSManagedObject *)dInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error{
NSError *superError = nil;
BOOL mappingSuccess = [super createRelationshipsForDestinationInstance:dInstance entityMapping:mapping manager:manager error:&superError];
if ([dInstance.entity.name isEqualToString:@"Rule"]){
Instance *instance = (Instance*)dInstance;
NSFetchRequest *fetch = [[NSFetchRequest alloc] initWithEntityName:@"Instance"];
fetch.predicate = [NSPredicate predicateWithFormat:@"identifier == %@",instance.identifier];
NSArray *result = [manager.destinationContext executeFetchRequest:fetch];
Rule *rule = [result objectAtIndex:0];
instance.rule = rule;
}
return YES;
}
然后,应用程序启动时将创建 Rule 和 Instance 之间的关系。
还要注意,由 NSEntityMigrationPolicy 的子类创建的关系不需要在 xcode 的迁移策略编辑窗口中设置值表达式,只需将其留空即可。