ios - Core Data 崩溃时出现错误 "dying managedobjectcontext"

标签 ios objective-c multithreading core-data xcode6.3

自从升级到 XCode 6.3 和 iOS 8.3 后,在将 NSManagedObjectContexts (MOC) 从后台合并到主线程 MOC 时,我的应用程序出现了一个新错误。

我的架构在主线程上有一个主 MOC,并在其他线程上创建了几个临时的后台 MOC,仅用于同步新的服务器数据。当这些后台 MOC 保存时,我会在主线程上监听通知 NSManagedObjectContextDidSaveNotification 并在主 MOC 上调用 mergeChangesFromContextDidSaveNotification

这是根据有关使用 Core Data 进行线程处理的文档(请参阅 Core Data Concurrency)。

这曾经工作得很好,但是从这个更新开始崩溃并出现这个错误,我无法追溯到我的代码的特定行:

illegally invoked -perform* on dying NSManagedObjectContext at:
    (
    0   CoreData                            0x28a2f273 <redacted> + 118
    1   CoreData                            0x28a32f09 <redacted> + 192
    2   CoreFoundation                      0x28c64e09 <redacted> + 12
    3   CoreFoundation                      0x28bbf515 _CFXNotificationPost + 1784
    4   Foundation                          0x29920749 <redacted> + 72
    5   Foundation                          0x2992522f <redacted> + 30
    6   Foundation                          0x29986a93 <redacted> + 98
    7   Foundation                          0x299867f7 <redacted> + 82
    8   Foundation                          0x299dfbd5 <redacted> + 408
    9   CoreFoundation                      0x28c72fed <redacted> + 20
    10  CoreFoundation                      0x28c706ab <redacted> + 278
    11  CoreFoundation                      0x28c709ff <redacted> + 734
    12  CoreFoundation                      0x28bbd201 CFRunLoopRunSpecific + 476
    13  CoreFoundation                      0x28bbd013 CFRunLoopRunInMode + 106
    14  GraphicsServices                    0x30359201 GSEventRunModal + 136
    15  UIKit                               0x2c361a59 UIApplicationMain + 1440
    16  MyAppName                           0x000c95a7 main + 170
    17  libdyld.dylib                       0x376c1aaf <redacted> + 2
)

我已经在 XCode 中打开僵尸,寻找释放的上下文,但没有找到。调用合并的主线程监听器如下所示:

- (void)coreDataDidSaveNotification:(NSNotification *)notification {
    NSManagedObjectContext *savedContext = (NSManagedObjectContext *)notification.object;

    if (savedContext != self.mainManagedObjectContext) {
        __weak typeof(self) weakSelf = self;
        [self.dispatch dispatchOnMainThread:^{
            NSLog(@"before merge");
            [weakSelf.mainManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
            NSLog(@"after merge");
        }];
    }
}

“合并后”的日志消息在崩溃发生之前被调用,这非常令人困惑。我已经在通知的背景上下文中检查了 retainCount,当合并被调用时它总是大于零,所以它不会在那个时候被释放。

知道发生了什么吗?

最佳答案

经过大量研究,我发现后台上下文确实在合并完成之前就已经释放了。 如果我保留对它们的引用,则不会发生崩溃。

看起来 mergeChangesFromContextDidSaveNotification 方法的行为发生了变化。持有上下文的通知过去足以保留它直到合并完成。

我相信现在发生的事情是 mergeChangesFromContextDidSaveNotification 方法现在在内部持有一个弱引用,并在内部分派(dispatch)主线程上的合并再次,将其排队等待下一个运行循环,这就是为什么我在崩溃发生之前看到“合并后”日志的原因。当合并在下一个运行循环中实际执行时,我已经释放了我对后台 MOC 的引用,并且当它超出范围时通知已经释放,并且由于内部引用现在可能 后台 MOC 被释放。

关于ios - Core Data 崩溃时出现错误 "dying managedobjectcontext",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29681794/

相关文章:

c# - 模型中的 ObservableCollection + ViewModel 中的线程

javascript - 从 iOS 中的 Safari 打开 Google Chrome 中的网页

ios - 如何使用CoreLocation获取多个iBeacon?

ios - 当用户点击 Objective C 中的 myLocation 按钮时如何执行操作?

iphone - objective-c : How to find heading (direction) from location services?

objective-c - 为什么我的 GCD 方法没有响应?

java使用线程来避免GUI死锁

ios - 如何修改AudioUnit Buffer的大小?

ios - UITabbar 在 iPad 和 iPhone 中的外观变化

ios - 成员(member)资格已过期 : now what for push notifications?