私の iPhone アプリケーションでは、2 つのエンティティ ( ItemとProperty )を持つ単純な Core Data Model を使用しています。
アイテム
名
のプロパティ
プロパティ
名
値
項目
Itemには 1 つの属性 (name) と 1 つの一対多の関係 ( properties ) があります。その逆の関係はitemです。プロパティには、逆の関係にある 2 つの属性があります。
ここで、データを 2 つのレベルのテーブル ビューに表示したいと考えています。最初のものはすべてのアイテムをリストします。1 つの行が選択されると、新しい UITableViewController が UINavigationController のスタックにプッシュされます。新しい UITableView は、選択した項目のすべてのプロパティ (つまり、それらの名前) を表示することになっています。
これを実現するためNSFetchedResultsController
に、インスタンス変数に格納された を使用します。最初のレベルでは、NSFetchedResultsController を次のように設定すると、すべてが正常に機能します。
-(NSFetchedResultsController *) fetchedResultsController {
if (fetchedResultsController) return fetchedResultsController;
// goal: tell the FRC to fetch all item objects.
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Item" inManagedObjectContext:self.moContext];
[fetch setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
[fetch setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetch setFetchBatchSize:10];
NSFetchedResultsController *frController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetch managedObjectContext:self.moContext sectionNameKeyPath:nil cacheName:@"cache"];
self.fetchedResultsController = frController;
fetchedResultsController.delegate = self;
[sort release];
[frController release];
[fetch release];
return fetchedResultsController;
}
ただし、第 2 レベルの UITableView では、何か間違っているようです。同様の方法で fetchedresultsController を実装しました。
-(NSFetchedResultsController *) fetchedResultsController {
if (fetchedResultsController) return fetchedResultsController;
// goal: tell the FRC to fetch all property objects that belong to the previously selected item
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
// fetch all Property entities.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Property" inManagedObjectContext:self.moContext];
[fetch setEntity:entity];
// limit to those entities that belong to the particular item
NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"item.name like '%@'",self.item.name]];
[fetch setPredicate:predicate];
// sort it. Boring.
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
[fetch setSortDescriptors:[NSArray arrayWithObject:sort]];
NSError *error = nil;
NSLog(@"%d entities found.",[self.moContext countForFetchRequest:fetch error:&error]);
// logs "3 entities found."; I added those properties before. See below for my saving "problem".
if (error) NSLog("%@",error);
// no error, thus nothing logged.
[fetch setFetchBatchSize:20];
NSFetchedResultsController *frController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetch managedObjectContext:self.moContext sectionNameKeyPath:nil cacheName:@"cache"];
self.fetchedResultsController = frController;
fetchedResultsController.delegate = self;
[sort release];
[frController release];
[fetch release];
return fetchedResultsController;
}
今、それは奇妙になっています。上記のNSLog
ステートメントは、選択したアイテムの正しい数のプロパティを返します。ただし、 UITableViewDelegate メソッドは、プロパティがないことを示しています。
-(NSInteger) tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
NSLog(@"Found %d properties for item \"%@\". Should have found %d.",[sectionInfo numberOfObjects], self.item.name, [self.item.properties count]);
// logs "Found 0 properties for item "item". Should have found 3."
return [sectionInfo numberOfObjects];
}
同じ実装は、最初のレベルでうまく機能します。
それはさらに奇妙になっています。プロパティを追加するために何らかの UI を実装しました。を介して新しいPropertyインスタンスを作成Property *p = [NSEntityDescription insertNewObjectForEntityForName:@"Property" inManagedObjectContext:self.moContext];
し、関係を設定して を呼び出します[self.moContext save:&error]
。これerror
はまだ機能しているようで、オブジェクトが保存されます ( Itemインスタンスをnil
ログに記録すると、プロパティの数を確認できます。上記を参照してください)。ただし、デリゲート メソッドは起動されません。これは、fetchRequest(Controller) がめちゃくちゃになっている可能性があるため、私には思えます。
何か案は?2 番目のフェッチ要求を台無しにしましたか? これは、特定のインスタンスの対多関係にあるすべてのエンティティを取得する正しい方法ですか?