使用AFIncrementalStore和NSFetchedResultsController死锁

这几天我一直在抨击我的头,不能为我的生活弄清楚是怎么回事。 我非常青睐核心数据,但我知道这足以避免死锁的情况。 然而,对于这个项目,我决定尝试并纳入AFIncrementalStore。 我构build了一个示例项目来testingAPIClient,以便恰当地映射键/值而不会干扰我的实际项目。 它工作完美无瑕。

现在我在我的实际项目中使用它,事情是挑剔的。 NSFetchedResultsController被用在一个UITableViewController中,这个UITableViewController被推出屏幕(在类似于Facebook应用程序的菜单中滑动)。 大约有50%的时间我没有陷入僵局。 我已经确定NSFetchedResultsController managedObjectContext和我的AppDelegate是一样的。 几乎所有的设置都与AFIncrementalStore示例相同。 即使我的示例项目,以testing使用完美的作品。

当我在死锁期间暂停时,以下是Debug Navigator的图像。 它看起来像AFIncrementalStore的后台上下文和主线程的上下文之间的问题。 但是我不知道该怎么做,因为我没有写AFIncrementalStore,而是刚刚离开现有的文档/示例。

调试导航器

编辑:添加第二个线程的回溯

thread #2: tid = 0x2103, 0x925d180e libsystem_kernel.dylib`semaphore_wait_trap + 10 frame #0: 0x925d180e libsystem_kernel.dylib`semaphore_wait_trap + 10 frame #1: 0x0258cf08 libdispatch.dylib`_dispatch_thread_semaphore_wait + 16 frame #2: 0x0258ab3a libdispatch.dylib`_dispatch_barrier_sync_f_slow + 149 frame #3: 0x0258aa5c libdispatch.dylib`dispatch_barrier_sync_f + 37 frame #4: 0x00b64c8b CoreData`_perform + 187 frame #5: 0x00b67659 CoreData`-[NSManagedObjectContext(_NestedContextSupport) managedObjectContextDidUnregisterObjectsWithIDs:] + 73 frame #6: 0x00bdf2db CoreData`__97-[NSManagedObjectContext(_NestedContextSupport) managedObjectContextDidUnregisterObjectsWithIDs:]_block_invoke_0 + 75 frame #7: 0x00b64cc1 CoreData`internalBlockToNSManagedObjectContextPerform + 17 frame #8: 0x0259b014 libdispatch.dylib`_dispatch_client_callout + 14 frame #9: 0x0258ad5f libdispatch.dylib`_dispatch_barrier_sync_f_invoke + 58 frame #10: 0x0258aaa3 libdispatch.dylib`dispatch_barrier_sync_f + 108 frame #11: 0x00b64c8b CoreData`_perform + 187 frame #12: 0x00b67659 CoreData`-[NSManagedObjectContext(_NestedContextSupport) managedObjectContextDidUnregisterObjectsWithIDs:] + 73 frame #13: 0x00b71c8c CoreData`-[NSManagedObjectContext(_NSInternalAdditions) _disposeObjects:count:notifyParent:] + 444 frame #14: 0x00b71305 CoreData`-[NSManagedObjectContext(_NSInternalAdditions) _dispose:] + 597 frame #15: 0x00b70e15 CoreData`-[NSManagedObjectContext _dealloc__] + 325 frame #16: 0x00bd872f CoreData`internalBlockToDeallocNSManagedObjectContext + 79 frame #17: 0x0259b014 libdispatch.dylib`_dispatch_client_callout + 14 frame #18: 0x0258b418 libdispatch.dylib`_dispatch_queue_drain + 239 frame #19: 0x0258b2a6 libdispatch.dylib`_dispatch_queue_invoke + 59 frame #20: 0x0258c280 libdispatch.dylib`_dispatch_root_queue_drain + 231 frame #21: 0x0258c450 libdispatch.dylib`_dispatch_worker_thread2 + 39 frame #22: 0x971cde12 libsystem_c.dylib`_pthread_wqthread + 441 

我不是一个CoreData的专家,所以拿一点盐。

看起来你可能正在使用NSPrivateQueueConcurrencyType。 看来AFIncrementalStore正在使用主队列进行同步。 那是在你的控制之下?

你可以尝试将您的NSManagedObjectContext切换到NSMainQueueConcurrencyType,看看是否有帮助?

现在,如果我是正确的,而且您正在使用NSPrivateQueueConcurrencyType,则可能是出于性能方面的考虑。 所以,这可能不是一个很好的长期解决scheme。

这个问题不是特定于使用AFIncrementalStore。 我们使用嵌套的上下文和NSFetched结果控制器遇到了同样的情况。

Child和Sibling上下文不需要使用相同的并发types,不需要使用相同的线程。 但是,你的获取的结果控制器必须在它的被pipe理对象上下文使用的同一个线程上使用,那你的debugging导航器中的线程2 NSManagedObjectContext队列让我觉得这可能是一个线程问题。

如果这是你的主要环境,有时这就像包裹你的胎儿一样简单

 dispatch_async(dispatch_get_main_queue(), ^{ [resultsController performFetch:nil]; }); 

或为真正的偏执狂

 [_resultsController.managedObjectContext performBlock:^{ [_resultsController performFetch:nil]; }]; 

这些死锁有很多东西,请尝试在这里和这里超过堆栈溢出post。