基本方法是
- 创建迁移 A 到 C 的策略
- 创建迁移 A 到 A 的策略
- 创建 B-to-B 迁移策略
以正确的顺序执行此操作很重要。
由于数据库中不存在 C,因此您必须做一个小技巧:NSMigrationManager
可以存储userInfo
. 这个 userInfo 字典在整个迁移过程中都可用。因此,您可以将您在 A-to-C 中创建的每个 C 对象存储在 userInfo 字典中。您需要在 A 上具有唯一标识符属性,以将其存储为键并将适当的 C 对象设置为值。在第三次迁移(B 到 C)中,您可以访问适当的 C 对象并将其分配给 B。
1. A-to-C:基于每个现有的 A 对象创建新的 C 对象。
在beginEntityMapping:manager:error:
创建您的初始NSMutableDictionary
并将其分配给NSMigrationManager
的 userInfo 属性。
在createDestinationInstancesForSourceInstance:entityMapping:manager:error:
执行以下操作:
- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error
{
NSMutableDictionary *cObjects = (NSMutableDictionary *)[manager userInfo];
NSObject *aUniqueIdentifierForEveryAObject = [sInstance valueForKey:@"aUniqueIdentifier"];
NSManagedObject *destinationC = nil;
if ([[cObjects allKeys] containObject:aUniqueIdentifierForEveryAObject])
{
newC = [userInfo objectForKey:aUniqueIdentifierForEveryAObject];
}
else
{
newC = [NSEntityDescription insertNewObjectForEntityForName:@"C" inManagedObjectContext:[manager destinationContext]];
// Assign instance A (sInstance) to the newC and update the userInfo
[newC setValue:sInstance forKey:@"a"];
[cObjects setObject:newC forKey:aUniqueIdentifierForEveryAObject];
}
[manager associateSourceInstance:sInstance withDestinationInstance:destinationC forEntityMapping:mapping];
return YES;
}
- (BOOL)createRelationshipsForDestinationInstance:(NSManagedObject*)dInstance entityMapping:(NSEntityMapping*)mapping manager:(NSMigrationManager*)manager error:(NSError**)error
{
return YES;
}
2. A-to-A:迁移所有A对象
这里可以对A的属性做一些额外的调整。重要的是,无论您是否有属性更改,都要创建此迁移,因为自动迁移已关闭。如果您没有任何更改,您可以简单地在映射模型编辑器中创建一个实体映射。
3. B-to-B:迁移所有B对象并分配新的C对象
分配新的 C 对象。你不能这样做,createRelationships...
因为你需要 A 对象和它的唯一标识符来从 userInfo 字典中获取适当的 C 。
- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error
{
id destinationB = [NSEntityDescription insertNewObjectForEntityForName:@"B" inManagedObjectContext:[manager destinationContext]];
NSMutableDictionary *userInfo = (NSMutableDictionary *)[manager userInfo];
NSMutableDictionary *cObjects = (NSMutableDictionary *)[userInfo valueForKey:kCObjects];
A *anA = [sInstance valueForKey:@"a"];
NSObject *aUniqueIdentifierForA = [anA valueForKey:@"aUniqueIdentifier"];
C *newC = [userInfo objectForKey:aUniqueIdentifierForA];
[destinationB setValue:newC forKey:@"c"];
// Migrate all other attributes here
[destinationB setValue:... forKey:...];
[manager associateSourceInstance:sInstance destinationB forEntityMapping:mapping];
return YES;
}
- (BOOL)createRelationshipsForDestinationInstance:(NSManagedObject *)dInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error
{
return YES;
}
我没有对此进行测试,但基本方法应该有效。
更新
第 1 步有一个错误:A-to-C。
// WRONG
[cObjects setObject:newC forKey:sInstance];
// UPDATED
[newC setValue:sInstance forKey:@"a"];
[cObjects setObject:newC forKey:aUniqueIdentifierForEveryAObject];