Ios NSManagedObjectContext-如何在父项更改时更新子项?

Ios NSManagedObjectContext-如何在父项更改时更新子项?,ios,core-data,nsfetchedresultscontroller,nsmanagedobjectcontext,Ios,Core Data,Nsfetchedresultscontroller,Nsmanagedobjectcontext,苹果公司的文档不清楚(或者我找不到)当parentMOC插入后保存时,父MOC和子MOC会发生什么情况 我使用的是MARCUS ZARRA的方法,上面是privateQMOC,childMainMOC是主线程 问题 我通过在privateMOC上调用save的后台internet请求将10000个对象添加到privateMOC,但在childMainMOC上下文上构建的任何NSFetchedResultsController在父级保存后都不会调用my delegate。因此,界面不会更新以显示p

苹果公司的文档不清楚(或者我找不到)当parentMOC插入后保存时,父MOC和子MOC会发生什么情况

我使用的是MARCUS ZARRA的方法,上面是privateQMOC,childMainMOC是主线程

问题

我通过在privateMOC上调用save的后台internet请求将10000个对象添加到privateMOC,但在childMainMOC上下文上构建的任何NSFetchedResultsController在父级保存后都不会调用my delegate。因此,界面不会更新以显示parentMOC中的更改

我想调用一些东西来更新childMainMOC中的所有对象,然后调用子控制器上的委托方法


或者其他解决方案

关键信息:

其余的上下文将是主队列上下文的子上下文

因此,处理下载数据的上下文必须是主上下文的子上下文,当您保存该子上下文时,您将保存主上下文,然后保存持久上下文


当您保存数据处理上下文时,它会立即通知父线程上下文,但您仍然需要保存两次才能将数据保存到磁盘上。

好的-所以我已经解决了所有问题

模型如下所示: 马库斯·扎拉 privateMOC是最根本的,这允许更好的性能,并且出于其他原因也需要这样做。我只使用2个MOC:私有根MOC和作为主线程的子MOC

然后读一读: 基本上,他解释了核心数据如何处理通知等。

然后——我需要做的最后一件事:确保程序中的所有objectid都是真正的永久对象

- (id)insertNewObjectForEntityName:(NSString *)entityName inManagedObjectContext:(NSManagedObjectContext *)context {

NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context];

// Make sure all inserted objects have a permanent ID.
// THIS IS VITAL. Without getting the permanentIDs, changes that come in from the web will not propogate to the child mainQ MOC and the UI will not update.
// Tested to be performant.
//NSLog(@"testing this - object.objectID is a temp now I think: %@ isTemp:%d", object.objectID, (int) [object.objectID isTemporaryID]);
// http://stackoverflow.com/questions/11990279/core-data-do-child-contexts-ever-get-permanent-objectids-for-newly-inserted-obj
NSError* error = nil;
[context obtainPermanentIDsForObjects:@[object] error:&error];
if (error || [object.objectID isTemporaryID])
    NSLog(@"obtainPermanentIDsForObjects is NOT WORkING - FIX: a new %@ isTemp: %d !!", entityName, (int) [object.objectID isTemporaryID]);

return object;
}

此外,我还需要按照本尼迪克特的文章——倾听父根私有MOC中的更改

/// . http://benedictcohen.co.uk/blog/archives/308  good info !
/// I need this firing as sometimes objects change and the save notification below is not enough to make sure the UI updates.
- (void)privateQueueObjectContextDidChangeNotification:(NSNotification *)notification {
    NSManagedObjectContext *changedContext = notification.object;
    NSManagedObjectContext *childContext = self.mainQueueObjectContext;
    BOOL isParentContext = childContext.parentContext == changedContext;
    if (!isParentContext) return;

    //Collect the objectIDs of the objects that changed
    __block NSMutableSet *objectIDs = [NSMutableSet set];
    [changedContext performBlockAndWait:^{
        NSDictionary *userInfo = notification.userInfo;
        for (NSManagedObject *changedObject in userInfo[NSUpdatedObjectsKey]) {
            [objectIDs addObject:changedObject.objectID];
        }
        for (NSManagedObject *changedObject in userInfo[NSInsertedObjectsKey]) {
            [objectIDs addObject:changedObject.objectID];
        }
        for (NSManagedObject *changedObject in userInfo[NSDeletedObjectsKey]) {
            [objectIDs addObject:changedObject.objectID];
        }      
    }];

    //Refresh the changed objects
    [childContext performBlock:^{
        for (NSManagedObjectID *objectID in objectIDs) {
            NSManagedObject *object = [childContext existingObjectWithID:objectID error:nil];
            if (object) {
                [childContext refreshObject:object mergeChanges:YES];
                //NSLog(@"refreshing %@", [object description]);
            }
        }
    }];
}
   - (void)privateQueueObjectContextDidSaveNotification:(NSNotification *)notification {
    //NSLog(@"private Q MOC has saved");
    [self.mainQueueObjectContext performBlock:^{
        [self.mainQueueObjectContext mergeChangesFromContextDidSaveNotification:notification];
        // I had UI update problems which I fixed with mergeChangesFromContextDidSaveNotification along with obtainPermanentIDsForObjects: in the insertEntity call.
    }];
}


不,相反。privateMOC是最根本的,这允许更好的性能,并且出于其他原因也需要这样做。我只使用了两个MOC,一个是私有根目录,另一个是子目录,这是一个主线程。那么你没有按照你链接到的页面的指导进行操作。。。使用您的方法,您必须在保存后将更改合并到主上下文中,这不会自动发生…我明白了-Marcus Zarra的页面在根目录下有一个privateQ。然后他就有了一条主线。这就是我正在做的。但是,在该主目录下建议多个隐私,这在进入系统的大多数数据来自非用户输入的设置中会遇到实际的性能问题。我在mainQ上有一个通知设置,这样我就可以知道用户何时编辑了某些内容。这样,我可以将这些编辑反映到云端。在mainMOC下的PrivateMOC中,幕后数据操作在mainMOC中显示为数千条通知。
    /// When the MainMOC saves - the user has changed data. 
/// We save up into the privateQ as well at this point. 
- (void)mainQueueObjectContextDidSaveNotification:(NSNotification *)notification {
    NSLog(@"main Q MOC has saved - UI level only changes only please");
    [self.privateQueueObjectContext performBlock:^{
        NSError* error = nil;
        if (self.privateQueueObjectContext.hasChanges) {
            [self.privateQueueObjectContext save:&error];
            if (error)
            {
                NSLog(@"Save up error - the actual datastore was not updated : %@", error);
            }
        } else {
            //NSLog(@"No need to save");
        }
    }];
}