私はNSFetchedResultsControllerと組み合わせてUITableViewControllerを実装しています。UITableViewController がインスタンス化されると、以前のコントローラーでユーザーが行った選択に基づいて、別の述語を使用して( CoreDataBooksの例と実質的に同じ方法で) NSFetchedResultsController が構築されます。
時々、次のように述語を設定します。
predicate = [NSPredicate predicateWithFormat:@"container = %@", aManagedObject];
時々このように:
predicate = [NSPredicate predicateWithFormat:@"container IN (%@)", aNSMutableSetOfObjectsID];
両方の述語は、期待どおりにすべてのオブジェクトを正しくフェッチするため、正常に機能します。2 番目の述語が設定されているときに、新しい管理対象オブジェクトをリストに挿入しようとすると、問題が発生します。実際、この場合、FRC デリゲート メソッドは呼び出されないため、テーブルビューは自動的に更新されません。
新しいオブジェクトが FRC で使用される同じコンテキストに正しく追加され、デリゲートがトリガーされるように「コンテナー」関係が設定されていることは確かですが、そうではありません!
私が試したこと:
新しいオブジェクトを追加してから UITableViewController をポップして再度プッシュすると、すべてのデータが強制的に再取得され、新しいオブジェクトが問題なくリストに表示されるため、2 番目の述語は正常に機能していると言えます。
私が行った別のテストは、新しいオブジェクトが追加された直後に FRC を強制的に再計算することです。
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
exit(-1);
}
[self.tableView reloadData];
新しいオブジェクトが正しく表示されます。
コード:
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController == nil) {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSManagedObjectContext *managedObjectContext = realEstate.managedObjectContext;
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Item" inManagedObjectContext:managedObjectContext]];
[fetchRequest setPredicate:[self getBasePredicate]];
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name"
ascending:YES
selector:@selector(localizedCaseInsensitiveCompare:)];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:nameDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[nameDescriptor release];
[sortDescriptors release];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:@"sectionIndex"
cacheName:nil];
self.fetchedResultsController = aFetchedResultsController;
fetchedResultsController.delegate = self;
[aFetchedResultsController release];
[fetchRequest release];
}
return fetchedResultsController;
}
// return a predicate for the fetchedResultsController
- (NSPredicate *)getBasePredicate {
NSPredicate *predicate = nil;
if ([[managedObject valueForKey:@"subcontainersCount"] intValue] == 0)
// container without sons **(FIRST PREDICATE)**
predicate = [NSPredicate predicateWithFormat:@"container = %@", managedObject];
else {
// container with sons **(SECOND PREDICATE)**
predicate = [NSPredicate predicateWithFormat:@"container IN (%@)", [Container allDescendantsObjectID:(Container *)managedObject includeSource:YES]];
}
return predicate;
}
- (void)addNewItem {
Item *newItem = (Item *)[NSEntityDescription insertNewObjectForEntityForName:@"Item"
inManagedObjectContext:realEstate.managedObjectContext];
newItem.name = @"my new item";
newItem.container = aContainerManagedObject;
NSError *error = nil;
if (![realEstate.managedObjectContext save:&error]) {
abort();
}
}
私が使用している NSFetchedResultsControllerDelegate メソッドは、「その他の iPhone 3 開発」から取られています。完全なコードは、ここ(30 ~ 31、35 ページ)で参照できます。
必要に応じてここに投稿できます。