使用两个托管对象上下文时,我在单个上下文中遇到同一实体的重复对象时遇到问题。
请考虑以下代码:
[childMOC performBlockAndWait:^{
// CREATE PERSON IN CHILD MOC
Person *person = [NSEntityDescription insertNewObjectForEntityForName:@"Person"
inManagedObjectContext:childMOC];
person.name = @"Ben";
// SAVE CHILD MOC TO PUSH CHANGES TO MAIN MOC
[childMOC save:nil];
NSManagedObjectID *personID = person.objectID;
[mainMOC performBlockAndWait:^{
// SAVE MAIN MOC TO PERSIST THE PERSON AND REPLACE ID TO PERMANENT
[mainMOC save:nil];
// GET THE PERSON IN THE MAIN MOC
Person *personInMainContext = (Person*)[mainMOC objectWithID:personID];
// GET THE PERSON'S NEW PERMANENT ID
NSManagedObjectID *personIdAfterSaveToPersistentStore = personInMainContext.objectID;
[childMOC performBlockAndWait:^{
// GET THE PERSON IN THE CHILD MOC WITH ITS NEW PERMANENT ID
// (this is common when sending the id from mainMOC to childMOC)
Person *samePersonFetchedFresh = (Person*)[childMOC objectWithID:personIdAfterSaveToPersistentStore];
// THE PERSON OBJECTS SHOULD BE EXACTLY THE SAME BECAUSE THE MOC GUARANTEES UNIQUING
samePersonFetchedFresh.name = @"Jerry";
NSLog(@"%@ & %@", person.name, samePersonFetchedFresh.name);
// OUTPUT: Ben & Jerry
// NOT THE SAME?!
}];
}];
}];
这意味着在子MOC中创建的对象在保存在主MOC /持久存储中时会失去其唯一的能力。
有人可以解释为什么在这种情况下,uniquing不起作用吗?
答案 0 :(得分:0)
在记录其名称之前尝试刷新您的人物。我认为unquing工作但缓存失效可能不会。
答案 1 :(得分:0)
在某处,您应该听取主要上下文NSManagedObjectContextDidSaveNotification
,并使用mergeChangesFromContextDidSaveNotification
将更改传播到子上下文。
如果完整合并不符合您的需求,您还可以使用refreshObject:mergeChanges:
单独更新每个实体。
如果您不想处理最新实例和旧副本,则必须以这种或那种方式传播更改。
这不是自动完成的,这是好事,因为操作可能非常繁重。对于相关的上下文,您必须在适当的时候处理合并。例如,如果您使用某些JSON服务填充数据库,则将使用上下文将实体添加到数据库,并且您希望在数据一致时更新UI,而不是每次将某些内容保存到数据库时主要上下文,也可能是磁盘。同样,该上下文肯定不会对UI中所做的更改感兴趣,然后保存到主上下文/磁盘。那么,这个过程不是自动的。
答案 2 :(得分:0)
我的解决方案是:
1)使用背景MOC作为父MOC,使用主MOC作为孩子。作为奖励,我不需要保存主MOC来获取永久ID。
[DC.backgroundMOC performBlock:^{
// Add, save and update managed objects
[DC saveContext]; // The changes is being pushed to the main context
}];
2)使用NSManagedObjectContextDidSaveNotification使主MOC保持最新状态(主要MOC正在更新UI)
- (void) backgroundMOCSaved:(NSNotification*)notification {
[mainMOC performBlock:^{
[mainMOC mergeChangesFromContextDidSaveNotification:notification];
}];
}