Core Data uniquing不起作用?

时间:2012-06-28 10:43:42

标签: objective-c ios core-data ios5 nsmanagedobjectcontext

使用两个托管对象上下文时,我在单个上下文中遇到同一实体的重复对象时遇到问题。

请考虑以下代码:

[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不起作用吗?

3 个答案:

答案 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];
    }];
}