CoreData(マルチスレッドの処理 )

CoreDataを扱う場合, main-threadのみでNSManagedObejctContextを利用している場合は, Appleのサンプルどおり, AppDelegateでSingleton実装でかまいません。しかし, NSOperationQueueや, dispatch_asyncなどのバックグラウンド処理でこのSingletonを呼び出すと, NSManagedObjectの何かしらの操作で落ちます。

例)

[_PFManagedObjectReferenceQueue _processReferenceQueue:]

しかも動作がぶつかったときだけ落ちるというなんとも見つけにくいものです。

下のReference通り, NSManagedObjectContextを新たに用意して, NSPersistentStoreCoordinatorはsingletonの分と共有します。さらに, backgroundで変更した結果を, main-threadに伝えるためのnotification, NSManagedObjectContextDidSaveNotificationを受け取ります。これは, 新たなcontext がsabveメソッドを発行したときに呼び出される, Notificationです。
最後に, main-threadへ統合するメソッドを実装します。

結局のところ, main-threadで利用していたSingletonのものはそのままキープです。コードの変更の必要はありません。バックグラウンド処理の部分のみ変更すればよいです。

サンプルコード(省略あり)

@interface BackgroundJob()
@property(nonatomic, readwrite, strong)NSManagedObjectContext *context;
@end

@implementation BackgroundJob
-(void)initThreadContext {
    self.context = [[NSManagedObjectContext alloc] init];
    [self.context setPersistentStoreCoordinator:[AppDelegate appdelegate].persistentStoreCoordinator];
    
    NSNotificationCenter *notify = [NSNotificationCenter defaultCenter];
    [notify addObserver:self
               selector:@selector(mergeChanges:)
                   name:NSManagedObjectContextDidSaveNotification
                 object:self.context];
    // Something to do 
}

- (void)mergeChanges:(NSNotification*)notification
{
    [[[AppDelegate appdelegate] managedObjectContext] performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) withObject:notification waitUntilDone:YES];
}

@end

initThreadContextを実行した後, 新たなcontextを使って処理を書きます。
persistentStoreCoordinator はAppDelegateで実装しているものです(Singleton)。
mergeChangesというメソッドで, main-threadとの統合を書きます, 同じクラス内であればこのように実装すれば対策は十分です。

Ref

マルチスレッドでCore Dataを利用する場合にはスレッドごとにManaged Object Contextを用意する
StackOverflow