【问题标题】:NSManagedObjectContextDidSaveNotification not triggered in iOS 7NSManagedObjectContextDidSaveNotification 未在 iOS 7 中触发
【发布时间】:2013-10-13 16:50:42
【问题描述】:

我有一种情况,我在主线程中对 NSManagedObject 的属性进行了一些更改。它属于应用程序的主 ManagedObjectContext。

我的应用确实启用了用于下载数据的线程,每个线程都有自己的 ManagedObjectContext,它是根据整个应用程序中单个 PersistentStore 的最新状态创建的。

我正在实现NSManagedObjectContextDidSaveNotification,以便 MOC 中的任何更改也合并回主线程的 MOC。下面是它的代码:

- (void)backgroundMOCDidSave:(NSNotification*)notification
{
    // Probable fix for: http://stackoverflow.com/questions/3446983/collection-was-mutated-while-being-enumerated-on-executefetchrequest
    if (![NSThread isMainThread])
    {
        [self performSelectorOnMainThread:@selector(backgroundMOCDidSave:) withObject:notification waitUntilDone:YES];
        return;
    }

    // We merge the background moc changes in the main moc
    [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}

注册此通知:

        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(backgroundMOCDidSave:)
                                                     name:NSManagedObjectContextDidSaveNotification
                                                   object:nil];

不过,iOS 7 中发生了奇怪的事情。我正在访问从主 MOC 创建的 NSManagedObject:

  • 当我修改属于主 MOC(主线程)的 ManagedObject 的属性并执行 -save 时,不会触发 -backgroundMOCDidSave: 调用
  • 当我不修改 ManagedObject 的任何属性而只对其 MOC 执行 -save 操作时,将触发通知

相同的代码在 iOS 6 中运行良好。无论是否对 ManagedObject 进行了任何更改,当在其 MOC 上触发 -save 调用时,将触发通知 NSManagedObjectContextDidSaveNotification

以前有人遇到过这个问题吗?

【问题讨论】:

  • 你的背景上下文是独立于主上下文还是嵌套在主上下文中?
  • 不,所有上下文都是从单个持久存储创建的。这就是为什么我将所有上下文的更改合并到将写入存储的主上下文中。
  • 如何检查backgroundMOCDidSave:是否被触发?
  • 我启用了断点。当我在 iOS 6 的 MOC 上调用 -save 时会遇到此断点,但在 iOS 7 中没有发生。

标签: cocoa-touch cocoa core-data nsmanagedobject nsmanagedobjectcontext


【解决方案1】:

现在我注意到一件事是错误的,但我不确定它是否会导致您的错误。 NSManagedObjectContextDidSaveNotification 在调用 save 的 MOC 正在运行的线程上发送。但是应该在运行 MOC 合并更改的线程上进行合并。在您的情况下,如果将更改从后台合并到主 MOC,则效果很好,但反之则不行。

【讨论】:

  • 是的,你提到的只是我的观点的一个断言。这里的实现有问题吗? DidSave 通知应该在主 MOC 上触发,因为它将(已经)写入持久存储,不是吗?
  • 我仔细看了看,发现您的实现无法处理从主 MOC 到后台 MOC 的合并更改。您需要另一种方法,例如mainMOCDidSave。然后,您必须更改对通知的订阅以依赖于上下文。您应该有两个订阅,而不是 object:nil];object:self.managedObjectContext];object:self.backgroundManagedObjectContext];
  • 好的,我现在明白你的意思了。除了主线程中的主 MOC,我为每个线程创建 MOC。所以,线程 MOC 的寿命不长。当我从服务器获取所有数据时,我确保只有在为线程创建 MOC 之后才在主 MOC 上调用 -save,这确保线程的 MOC 是从持久存储的最新状态创建的。但对我来说,问题不在于辅助线程,而在于 MOC。相反,当我执行 -save 操作时,对主 MOC 的 ManagedObject 所做的更改不会触发 NSManagedObjectContextDidSaveNotification。
  • 是的,我不知道为什么会这样。保存主 MOC 时是否检查错误?
  • 谢谢,我错过了检查保存错误。它正在放弃 NSMergeConflict。但是,这导致我遇到其他人已经在 SO 中发布的另一个问题:stackoverflow.com/questions/19178972/nsmergeconflict-on-ios7 但这可以标记为已解决,谢谢。
猜你喜欢
  • 2019-11-24
  • 2019-09-12
  • 2014-12-17
  • 2011-12-08
  • 1970-01-01
  • 1970-01-01
  • 2020-12-26
  • 1970-01-01
  • 2015-09-07
相关资源
最近更新 更多