ios - NSManagedObjectContext - 如何在 parent 改变时更新 child ?

标签 ios core-data nsfetchedresultscontroller nsmanagedobjectcontext

Apple 文档不清楚(或者我找不到)关于当父 MOC 插入后保存时父 MOC 和子 MOC 会发生什么。

我正在使用 MARCUS ZARRA 的 http://martiancraft.com/blog/2015/03/core-data-stack/方法,顶部有一个 privateQMOC,childMainMOC 作为主线程。

问题

我通过在 privateMOC 上调用保存的后台互联网请求将 10,000 个对象添加到 privateMOC,但是在父级保存后,在 childMainMOC 上下文上构建的任何 NSFetchedResultsControllers 都不会调用我的委托(delegate)。因此界面不会更新以显示 parentMOC 中的更改。

我想调用一些东西来更新 childMainMOC 中的所有对象 - 然后应该调用子 Controller 上的委托(delegate)方法。

或者其他一些解决方案。

最佳答案

好的 - 所以我想通了。

模型如下: 马库斯·扎拉的 http://martiancraft.com/blog/2015/03/core-data-stack/ privateMOC 位于根部,这样可以获得更好的性能,并且出于其他原因也需要这样做。我只使用 2 个 MOC:私有(private)根和子线程,它是一个主线程。

然后读这个: 基本上他解释了 Core Data 如何处理通知等。 http://benedictcohen.co.uk/blog/archives/308

然后 - 我需要做的最后一件事:确保程序中的所有 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;

我还需要按照 Benedicts 的文章 - 监听父根私有(private) 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.
    }];

    /// 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");
        }
    }];
}

关于ios - NSManagedObjectContext - 如何在 parent 改变时更新 child ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36338135/

相关文章:

ios - 解析 Swift IOS - 未调用 PFCloud callFunctionInBackground 选择器

ios - 使用_框架!和库 repo 根目录中的 podspec

ios - UIPopover:UISegmentedControl 而不是标题

ios - 更新 NSManagedObject 导致 NSFetchedResultsController 删除

objective-c - 从角落调整 uiview 的大小

ios - 如何在 Swift 的核心数据中保存多个项目

swift - 需要通用的 FetchedResultsController 构建器(Swift)

iphone - 偶尔 "Illegal attempt to establish a relationship ' .. .' between objects in different contexts"

objective-c - NSFetchedResultsController 与搜索

objective-c - 为什么删除对象时不触发 NSFetchedResultsChangeDelete?