Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSFetchedResultsController / Parent-Child

I'm working on my first Core Data-backed app and am having trouble figuring out how to set up an NSFetchedResultsController properly. I have two entities:

/-----------\        /-----------\
| List      |        | ListItem  |
| --------- |        | --------- |
| listName  |        | itemName  |
| --------- |        | --------- |
| listItems |<---->> | list      |
\ --------- /        \ --------- /

I have two views (each inherit from UITableViewController and each are backed by a NSFetchedResultsController). The first view is a UITableView that displays all of the List items. When a row is selected, it pushes the second view.

I have a property in the view controller called @property (strong, nonatomic) List *selectedList which I assign with the selected List before I push the view.

What I'm having trouble setting up is having the second view only display the ListItem objects whose parent is the selected List. I know that this belongs somewhere in the NSFetchedResultsController, but I don't know quite where.

Here's my code:

- (NSFetchedResultsController *)fetchedResultsController
{
    if (__fetchedResultsController != nil) {
        return __fetchedResultsController;
    }

    // Set up the fetched results controller.
    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"ListItem" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO];
    NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];

    [fetchRequest setSortDescriptors:sortDescriptors];

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Detail"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return __fetchedResultsController;
}    

Do I need to add some sort of a sort descriptor, or does the answer lie with something else? Thanks!

like image 524
Fred Jenkins Avatar asked Dec 19 '11 21:12

Fred Jenkins


1 Answers

You need an NSPredicate to select the ListItems where selectedList matches their list property.

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"list == %@", self.selectedList];
[fetchRequest setPredicate:predicate];

There's one thing to be aware of here and that is that the predicate will change depending on selectedList meaning that the fetch request will change. If you will be changing the fetch request, Apple has this warning in the NSFetchedResultsController Class Reference.

You cannot simply change the fetch request to modify the results. If you want to change the fetch request, you must:

  1. If you are using a cache, delete it (using +deleteCacheWithName:).

  2. Typically you should not use a cache if you are changing the fetch request.

  3. Change the fetch request. Invoke -performFetch:.

like image 187
Mark Adams Avatar answered Sep 19 '22 16:09

Mark Adams