2

私はここ数日間、これに対して頭を悩ませてきましたが、何が起こっているのか理解できません。私は Core Data にかなり慣れていますが、デッドロック シナリオを回避するのに十分なほどよく知っています。ただし、このプロジェクトでは、AFIncrementalStore を試して組み込むことにしました。実際のプロジェクトをいじらずにキー/値を適切にマッピングするために、APIClient をテストするサンプル プロジェクトを作成しました。それは完璧に機能しました。

今、私は実際のプロジェクトでそれを使用していますが、物事は厄介です。NSFetchedResultsController は、画面から押し出される UITableViewController で使用されます (Facebook アプリに似たメニューでスライドします)。約 50% の場合、デッドロックは発生しません。NSFetchedResultsController managedObjectContext が AppDelegate と同じであることを確認しました。ほとんどすべてが AFIncrementalStore の例と同じように設定されています。使用法をテストするための私のサンプル プロジェクトでさえ、完全に機能します。

デッドロック中に一時停止したときの Debug Navigator のイメージを次に示します。AFIncrementalStore のバックグラウンド コンテキストとメイン スレッドのコンテキストの間に問題があるようです。ただし、 AFIncrementalStore を作成しておらず、既存のドキュメント/例から離れているだけなので、どうすればよいかわかりません。

デバッグナビゲーター

編集:2番目のスレッドのバックトレースを追加

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
4

2 に答える 2

4

この問題は、AFIncrementalStoreの使用に固有のものではありません。ネストされたコンテキストとNSFetched結果コントローラーを使用するだけでも同じことが起こりました。

子コンテキストと兄弟コンテキストは同じ同時実行タイプを使用する必要はありません。同じスレッドを使用する必要はありません。ただし、フェッチされた結果コントローラーは、管理対象オブジェクトコンテキストが使用するのと同じスレッドで使用する必要があります。デバッグナビゲーターのスレッド2 NSManagedObjectContextキューにより、これはおそらくスレッドの問題であると思われます。

これがあなたの主な文脈である場合、これはあなたのフェットをこのように包むのと同じくらい簡単です

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

または本当にパラノイドのために

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

これらのデッドロックにはたくさんのものがあります。ここここでオーバースタックオーバーフローの投稿を試してください。

于 2013-02-26T14:55:58.087 に答える
2

私は決して CoreData の専門家ではありません。

おそらく、NSPrivateQueueConcurrencyType を使用しているようです。AFIncrementalStore が同期のためにメイン キューを使用しているようです。それはあなたの管理下にありますか?

NSManagedObjectContext を NSMainQueueConcurrencyType に切り替えてみて、それが役立つかどうかを確認できますか?

さて、私が正しく、NSPrivateQueueConcurrencyType を使用している場合、おそらくパフォーマンス上の理由でそれを行っているでしょう。したがって、これは優れた長期的な解決策ではないかもしれません...

于 2013-02-26T14:30:12.477 に答える