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 ?
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.