in my iPhone application I use a simple basic data model with two objects ( Element and Property ):
Item
name
properties
Property
name
value
item
An element has one attribute (name) and one one-to-many relationships (properties). His feedback is an element. The property has two attributes in accordance with the inverse relationship.
Now I want to show my data in a table view at two levels. The first list lists all the items; when one row is selected, the new UITableViewController is pushed onto my UINavigationController stack. The new UITableView should show all the properties (for example, their names) of the selected item.
For this, I use the NSFetchedResultsController stored in the instance variable. At the first level, everything works fine when setting up NSFetchedResultsController as follows:
-(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; }
However, on the second level UITableView, I seem to be doing something wrong. I implemented fetchedresultsController in a similar way:
-(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; }
Now it is getting weird. The above NSLog statement returns me the correct number of properties for the selected item. However, the UITableViewDelegate method tells me that there are no properties:
-(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]);
The same implementation works fine on the first level.
It gets even weirder. I implemented some kind of user interface for adding properties. I create a new instance of Property through Property *p = [NSEntityDescription insertNewObjectForEntityForName:@"Property" inManagedObjectContext:self.moContext]; , configure the relationship and call [self.moContext save:&error] . This seems to work, since error is still nil and the object is saved (I can see the number of properties when registering an instance of the Element , see above). However, delegate methods do not start. This seems to me because of the possible spoiled fetchRequest (Controller).
Any ideas? Did I mess up the second fetch request? Is this the right way for all objects in many ways for a particular instance?