NSFetchedResultsController に接続されたテーブル ビューがあり、対応する managedObjectContext は self.myDatabase.managedObjectContext です。
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.myDatabase.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
ここで、ユーザーがページを更新するたびに、次のコードを実行します。本質的に、データをロードする新しいスレッドを作成し、MOC セーフ スレッドで新しいデータを更新/保存します。
dispatch_queue_t fetchQ = dispatch_queue_create("fetcher", NULL);
dispatch_async(fetchQ, ^{
NSArray *data = [MyAPI myData];
[document.managedObjectContext performBlock:^{
for (NSDictionary *info in data) {
[MyEntity createOrUpdateGivenInfo:info andManagedObjectContext:self.myDatabase.managedObjectContext];
}
}];
});
dispatch_release(fetchQ);
これは正常に機能します。更新を取得すると、テーブル ビューにすべてが正しく表示されます。唯一の問題は、おそらくメインスレッドで保存/更新を行っているため、UI が応答しないことです。そこで、この変更を加えてバックグラウンド スレッドで実行することを検討しました。
NSManagedObjectContext *backgroundContext = [[NSManagedObjectContext alloc] init WithConcurrencyType:NSPrivateQueueConcurrencyType];
[backgroundContext setParentContext:self.myDatabase.managedObjectContext];
[backgroundContext performBlock:^{
NSArray *data = [MyAPI myData];
for (NSDictionary *info in data) {
[MyEntity createOrUpdateGivenInfo:info andManagedObjectContext:backgroundContext];
}
[backgroundContext save:nil];
[document.managedObjectContext performBlock:^{
[document updateChangeCount:UIDocumentChangeDone];
}];
}];
ただし、UI はレスポンシブになりましたが、テーブル ビューで多くの問題が発生します。既存のエントリを更新する代わりに、テーブルに余分なエントリ (存在しないはずの重複) が表示されます。2 つのコンテキストが同期/マージされていないことが原因である可能性があると思いますが、以前の SO の投稿を読んで、backgroundContext で save を呼び出し、メイン MOC で updateChangeCount を呼び出すだけでよいと考えるようになりました。アプリを再起動すると、もう一度更新するまで、すべてが正常に機能します。
誰でも助けてくれる人はいますか。私は文字通り私の髪を引っ張り始めています。
この謎が解けたらビールを差し上げます。