views:

28

answers:

1

Problem:

I'm implementing an UITableViewController in conjunction with NSFetchedResultsController. When the UITableViewController is instantiated the NSFetchedResultsController is constructed (substantially in the same way as CoreDataBooks example) with a different predicate, based on selection the user made on the previous controller.
Sometimes I set the predicate in this way:

predicate = [NSPredicate predicateWithFormat:@"container = %@", aManagedObject];

sometimes in this way:

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

Both predicates works fine because they fetch correctly all my objects as expected. The problem occur when I try to insert a new managed object into the list when the second predicate is setted. Infact in this case the FRC delegate methods are never called, so the tableview is not automatically updated.
I'm sure the new object is correctly added to the same context used by the FRC, and that its "container" relation is set so that the delegate should be triggered, but it doesn't!

What I have tried:

I say that the second predicate is working fine because if I add a new object and then pop the UITableViewController and push it again, forcing all data to be refetched, the new object appear in the list without problem.
Another test I made is to force the FRC to be recalculated immediatelly after the new object is added:

NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
    exit(-1);
}
[self.tableView reloadData];

the new object appear correctly.

Code:

- (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();
    }
}

The NSFetchedResultsControllerDelegate methods I'm using are taken from the "More iPhone 3 Development". The complete code can be see here (pages 30-31, 35).
I can post here if needed.

Thanks for any help.

A: 

Solved replacing the objects ID with NSManagedObject into the predicate.
Before: [NSPredicate predicateWithFormat:@"container IN (%@)", aNSMutableSetOfObjectsID]; After: [NSPredicate predicateWithFormat:@"container IN (%@)", aNSMutableSetOfNSManagedObject];

For some reasons the FRC delegate is not called if predicate fetch objects using ID instead of exact NSManagedObjects.
I'm testing on iPhoneOS 3.1.3 and 3.2. However iPhoneOS 4.0 should support both objectsID and NSManagedObject and correctly call the FRC delegate methods, but I can't test on 4.0 for now.

ggould75