at_yasu's blog

ロード的なことを

CoreDataとMultiThreadのメモ書き(不完全)

いまいち分かってないけどメモ書き

*2010/12/14 追加、基本ルールにすこし追記
*2010/12/17 追加、ごにょごにょと。

Stackoverflowに書いている事ではこんな感じ。

基本ルール

  • NSPersistentStoreCoordinator は唯一にすること
    • 同様に、NSManagedObjectModelも唯一になりますよっと。
  • NSManagedObjectContext はスレッドごと
  • 絶対に、他のスレッドにNSManagedObjectを渡さない
    • 渡す場合は、objectIDを渡してそれを元に取得
      • ただし注意が必要で、保存していない時、objectIDを渡してもtempIDなので意味がありませんですよっと。
    • 保存したらmainthreadのNSManagedObjectContext に mergeChangesFromContextDidSaveNotification: を投げて。

上だと、例えばネットから落としてきてDBに放りこむ処理をスレッドにやっても、メインスレッドには反映されないので、表示上は何も無しになるという頭の痛い事になります。ですので、Using Core Data on Multiple Threads | Duck Rowingでは、NSManagedObjectContextDidSaveNotification: が飛んできたらメインスレッドにある NSManagedObjectContext に mergeChangesFromContextDidSaveNotification: を投げています。


Using Core Data on Multiple Threads | Duck Rowing の例文

- (void)main
{
 
...
  // Create context on background thread
  ApplicationController *appController = [[NSApplication sharedApplication] delegate];
 
  NSManagedObjectContext *ctx = [[NSManagedObjectContext alloc] init];
  [ctx setUndoManager:nil];
  [ctx setPersistentStoreCoordinator: [appController persistentStoreCoordinator]];

  // Register context with the notification center
  NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 
  [nc addObserver:self
         selector:@selector(mergeChanges:)
             name:NSManagedObjectContextDidSaveNotification
           object:ctx];
 
...
 
}

- (void)mergeChanges:(NSNotification *)notification
{
  ApplicationController *appController = [[NSApplication sharedApplication] delegate];
  NSManagedObjectContext *mainContext = [appController managedObjectContext];
 
  // Merge changes into the main context on the main thread
  [mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
                                withObject:notification
                             waitUntilDone:YES];  
}

不思議なことにこれをすると、insertしたオブジェクトも反映されます。
メインスレッドにも、 NSManagedObjectContextDidSaveNotification: を登録したらいいんじゃないのかという疑問もありますが、うまくいかなくて、意図的に投げてやらないと期待通りに動いてくれませんでした。

参考: