0

我在合并不同 NSManagedObjectContexts(iOS 6.1、Xcode 4.6)的数据时遇到问题/崩溃。

大多数情况下,上升的错误如下:

CoreData:错误:严重的应用程序错误。在核心数据更改处理期间捕获到异常。这通常是 NSManagedObjectContextObjectsDidChangeNotification 观察者中的一个错误。使用 userInfo (null) 的语句仍处于活动状态

有一次我得到这个错误: NSManagedObjectContextDidSaveNotification 的观察者非法抛出异常。已保存的对象 = { $OBJLIST } 和异常 = 语句仍处于活动状态,且 userInfo = (null)

可悲的是,我得到的堆栈跟踪没有任何价值。它们只显示 CoreData 内部的符号(如果有)。

我们的 CoreData 堆栈:

  • 1 个 NSPersistentStoreLocator 由所有线程共享
  • 每个线程 1 个唯一的 MOC(在第一次需要时创建)
    • 所有 MOC 都保存在字典中

为通知 NSManagedObjectContextDidSaveNotification 添加了一个观察者,以在保存到商店时更新 MOC。定义的选择器在除执行保存操作的线程/上下文之外的所有其他线程/上下文上调用 mergeChangesFromContextDidSaveNotification。

+ (void)mergeChanges:(NSNotification *)notification {
    NSManagedObjectContext *ctx;
    for ( NSNumber *threadId in [__managedObjectContexts keyEnumerator] ) {
        ctx = [__managedObjectContexts objectForKey:threadId];
        if ( notification.object != ctx ) {
            [ctx mergeChangesFromContextDidSaveNotification:notification];
        }
    }
}

产生错误的步骤:

在后台线程中,不再需要的 CoreData 数据对象(未被其他对象引用)正在被删除。

[[CDUtils managedObjectContext] deleteObject:obj];
[[CDUtils managedObjectContext] save:&error];

发生这种情况时,用户可以在整个应用程序中导航。用户交互(即打开一个tableview)可以在主线程的moc 上触发executeFetch 调用。每个线程使用相同的 NSPersistentStoreLocator 但不同/唯一的 MOC。

我们尝试了使用 NSLocks 和 NSPersistentStoreLocator 上的锁来确保线程安全的不同方法。即通过锁定/解锁将mergeChanges 方法和保存操作分别包含在同一个锁定/解锁中,或者将这两种方法包含在同一个锁定/解锁中。遗憾的是,到目前为止我们还没有成功。

[__storeCoordinator lock];
[__storeCoordinator unlock];

我会很感激你给我的每一条建议来解决问题。感谢您的时间!

4

1 回答 1

0

对于有兴趣的人。我设法使事情与多个线程/ MOC 一起工作。通过正确锁定 PSC 和 MOC,我基本上解决了最初的问题/那些错误。出现的下一个问题是如何知道它是否保存到上下文中的 mergeChanges。我不能锁定也不应该在没有运行线程的 MOC 上进行 mergeChanges。但是我怎么知道线程是否正在运行?如果我只是检查 NSThreads “isExecuting”-Method,那么线程可能会在我检查 BOOL 之后立即退出。我现在尝试一种更简单的方法,我只是合并到主线程中。

于 2013-07-05T15:46:47.337 回答