をNSFetchedResultsController
介して別のスレッドで管理対象オブジェクトを更新する操作がいくつかありますNSOperationQueue
。
FRC(述語付き)は次のようになります。
- (NSFetchedResultsController*)fetchedResultsController
{
if(fetchedResultsController) return fetchedResultsController;
NSManagedObjectContext* mainContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Check" inManagedObjectContext:mainContext]];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"isSync == %@", [NSNumber numberWithBool:NO]]];
[fetchRequest setFetchBatchSize:10];
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:mainContext sectionNameKeyPath:nil cacheName:nil];
fetchedResultsController.delegate = self;
[fetchRequest release], fetchRequest = nil;
return fetchedResultsController;
}
メインスレッドとスレッド化された操作には、独自の管理対象オブジェクトコンテキストがあります。彼らは同じコーディネーターを共有するだけです。
スレッド化された操作内で、isSync
プロパティをからNO
に変更しますYES
。更新するエンティティを知るためCheck
に、メインコンテキストはスレッド化されたエンティティに渡されますNSManagedObjectID
。スレッド化された操作は、次のように管理対象オブジェクトを取得します。
-(void)main
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSManagedObjectContext *exportContext = [[NSManagedObjectContext alloc] init];
[exportContext setPersistentStoreCoordinator:[self persistentStoreCoordinator]];
//...
Check* check = (Check*)[exportContext existingObjectWithID:objID error:&error];
check.isSync = [NSNumber numberWithBool:YES];
//...
[exportContext save:&error];
[pool release], pool = nil;
}
スレッド操作が通知を呼び出すとsave
、mergeChangesFromContextDidSaveNotification
通知が呼び出され、メインコンテキストが変更をマージします。
- (void)contextChanged:(NSNotification*)notification
{
if ([notification object] == [self managedObjectContext]) return;
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(contextChanged:) withObject:notification waitUntilDone:YES];
return;
}
[[self managedObjectContext] mergeChangesFromContextDidSaveNotification:notification];
}
リードの説明をログに記録しnotification
て、変更が正しく実行されていることを確認します。
私の問題
のデリゲートメソッドはNSFetchedResultsControllerDelegate
呼び出されません。
同じコンテキスト(メインコンテキスト)を処理すると、変更をリッスンでき、デリゲートメソッドが呼び出されるため、これは非常に奇妙です。たとえば、の行オブジェクトを削除しますUITableView
。
同じ問題のあるSOに関するトピックをいくつか見つけました。私はすべての回避策を試しましたが、価値のある解決策を見つけることができません:
バックグラウンドスレッドからの更新をマージした後、NSFetchedResultsControllerがデリゲートメソッドを起動しません
述部を持つNSFetchedResultsControllerは、異なるNSManagedObjectContextからマージされた変更を無視します
前もって感謝します。
編集
上記のコードは以前のモデルで機能していました。次に、前のモデルからエンティティをコピー(および貼り付け)する新しいモデルを作成しましたが、現在は機能しません。
提案?
編集2
これは私がNSFetchedResultsController
getterで使用している述語です。それは私のせいですが、私が投稿を書いたとき、私はそれをコピーしませんでした。
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"insertionDate" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
// previous code here
[fetchRequest setSortDescriptors:sortDescriptors];
さて、ジョディについて最後のコメント
NSOperationのmain()で、新しいオブジェクトをロードしています。そこでは、新しいオブジェクトごとにisSyncをYESに設定しているように見えます。fetchedResultsControllerに使用する述語は、isSync==NOを持つオブジェクトのみを検索します。
プロパティisSync
がYESに設定されている場合NSFetchedResultsController
、述語に一致しない行が変更および削除されることを監視します。私が間違っている?
バックグラウンドからメインスレッドへの変更をマージするときに、isSync
プロパティを更新したオブジェクトがほとんどないことがわかります。