如何通知主 MOC,后台 MOC 的变化

Posted

技术标签:

【中文标题】如何通知主 MOC,后台 MOC 的变化【英文标题】:How to notify main MOC, changes in background MOC 【发布时间】:2015-02-04 12:19:27 【问题描述】:

我正在使用线程在 coreData 中处理并发,我按照苹果的示例进行操作,链接在这里https://developer.apple.com/library/ios/samplecode/ThreadedCoreData/Introduction/Intro.html 我对这个示例项目没有什么疑问

我正在使用一个类调用 PullOperation,它是 NSOperation 的子类,所以当 pull 发生时,

我想通知我的主要 MOC,有关更改,以便更新并显示在 tableView 上

我想知道怎么做?

按照示例应用,我在 appdelegate.m 中编写了这段代码

  - (NSManagedObjectContext *)managedObjectContext 

        if (_managedObjectContext != nil) 
            return _managedObjectContext;
        

        NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
        if (coordinator != nil) 
            _managedObjectContext = [NSManagedObjectContext new];
            [_managedObjectContext setPersistentStoreCoordinator:coordinator];
        

        // observe the ParseOperation's save operation with its managed object context
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(mergeChanges:)
                                                     name:NSManagedObjectContextDidSaveNotification
                                                   object:nil];

        return _managedObjectContext;
    

    // merge changes to main context,fetchedRequestController will automatically monitor the changes and update tableview.
    - (void)updateMainContext:(NSNotification *)notification 

        assert([NSThread isMainThread]);
        [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
    

    // this is called via observing "NSManagedObjectContextDidSaveNotification" from our APLParseOperation
    - (void)mergeChanges:(NSNotification *)notification 

        if (notification.object != self.managedObjectContext) 
            [self performSelectorOnMainThread:@selector(updateMainContext:) withObject:notification waitUntilDone:NO];
        
    

在这里我们可以看到合并变更的通知。

但是我的应用卡住了并且没有响应,并且我收到消息说应用由于内存问题而停止。

所以我想知道我哪里出错了。

请帮忙

问候 兰吉特

【问题讨论】:

请贴上你自己的代码,再贴更多的代码,你这里贴的代码好像没有问题 @CarmeloS,只是编辑问题 您好@CarmeloS,请检查已编辑的问题 请显示日志,这可能会有所帮助 @CarmeloS,没有日志,如果我只是在上述方法中添加这些通知行,我的应用程序就会停止 【参考方案1】:

如果您的应用程序在托管对象上下文更改时停止,我想这是因为您的两个托管对象上下文相互观察(通过收听NSManagedObjectContextDidSaveNotification),因此当发生更改时,它将形成一个无休止的递归调用。

但是我没有足够的代码,所以我只是猜测,我建议你在这一行下一个断点:

[self performSelectorOnMainThread:@selector(updateMainContext:) withObject:notification waitUntilDone:NO];

并触发更改以查看此行是否多次输入。如果是,那我的猜测是对的。

编辑:

通过聊天,我得到了更多信息,问题是因为PO使用GAI(Google Analytics SDK for iOS)GAI使用核心数据进行数据持久化并且GAI有自己的核心数据堆栈,当GAI保存时它的上下文,它将发布NSManagedObjectContextDidSaveNotification,并且此通知全局,触发-mergeChanges:,在-mergeChanges:,应用程序将尝试将GAI's context与应用程序的上下文合并,这两个context 正在使用不同的持久存储协调器,这会导致问题。

为了解决这个问题,我们需要检查源上下文是否使用与目标上下文相同的协调器,如果不是,则不合并。

【讨论】:

我几乎不知道发生了什么。当我重新启动我的应用程序并且没有调用背景上下文时,我也看到调用了 updateMaincontext。但它不应该被称为对吗? @Ranjit 在 -mergeChanges 处设置断点:查看是谁触发了它 我怎么知道? @Ranjit NSNotificationCenter 同步工作,因此当断点触发时,您可以跟踪调用堆栈,您将看到触发通知的上下文保存调用。 你的问题太具体了,不知道代码很难解决。

以上是关于如何通知主 MOC,后台 MOC 的变化的主要内容,如果未能解决你的问题,请参考以下文章

CoreData 在后台 MOC 的保存操作期间无法完成故障

UndoManager 和多个 MOC

CoreData prepareForDeletion 调用无限次

应用程序设计:处理带有背景上下文的核心数据;合并由 MOC 过滤的通知

在后台线程中更新托管对象上下文

CoreData SIGABRT 同时保存主 MOC。为啥?