3

私は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 ページ)で参照できます。
必要に応じてここに投稿できます。

4

1 に答える 1

2

NSManagedObjectオブジェクト ID を述語に 置き換えることで解決しました。

前:[NSPredicate predicateWithFormat:@"container IN (%@)", aNSMutableSetOfObjectsID];

後:[NSPredicate predicateWithFormat:@"container IN (%@)", aNSMutableSetOfNSManagedObject];

述語が正確な NSManagedObjects の代わりに ID を使用してオブジェクトをフェッチする場合、何らかの理由で FRC デリゲートが呼び出されません。
iPhoneOS 3.1.3 および 3.2 でテストしています。ただし、iPhoneOS 4.0 は objectsID と NSManagedObject の両方をサポートし、FRC デリゲート メソッドを正しく呼び出す必要がありますが、今のところ 4.0 でテストすることはできません。

于 2010-07-03T12:24:56.120 に答える