Search code examples
iosuitableviewcore-datansfetchedresultscontroller

NSFetchedResultsController delegate method calls on predicate change


I have a simple app, where I have countries which have cities, which in turn have people. I want to display list of countries in a table view. I use NSFetchedResultsController to get all the data. This is the setup :

-(void)initializeFetchedResultsController
{
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Country"];
    fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]];
    fetchRequest.fetchBatchSize = 30;
    self.fetchResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                                                      managedObjectContext:[NSManagedObjectContext managedObjectContext]
                                                                        sectionNameKeyPath:@"nameFirstLetter"
                                                                                 cacheName:nil];
    self.fetchResultsController.delegate = self;
    [self.fetchResultsController performFetch:nil];
}

I also added an ability to search by typing in the country name in the search bar, so I implemented UISearchBarDelegate method :

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    if([searchText isEqualToString:@""])
    {
        self.fetchResultsController.fetchRequest.predicate = nil;
    }
    else
    {
        self.fetchResultsController.fetchRequest.predicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH[cd] %@", searchText];
    }

    [self.fetchResultsController performFetch:nil];
    [self.tableView reloadData];
}

This works but not the way I want. I expected that on predicate change, my NSFetchResultsControllerDelegate delegate methods will be called again so I can insert or delete items / sections from my table view (i want animations) without having to figure out myself, what has been added and removed. But this is not the case, instead if I change the predicate, delegate methods are not called, and I must do a simple [self.tableView reloadData]. Am I doing something wrong or is it just the way it is supposed to work, and I cannot take this shortcut ?


Solution

  • As @StianHøiland says, you need to do it yourself. Generally with delegate methods they are called as a result of an 'offline' / asynchronous change in order to notify you. They are not called as a result of a change you have explicitly requested.

    You could think about using the fetchedObjects and the indexPathForObject: features of the FRC. Filter the fetchedObjects list (using your predicate). Get the index paths for the objects that have been removed and you can animate them out.