Reputation: 13073
My fetchedResultsController is initially created like this (in viewDidLoad):
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Cat" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:@"age" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"age"
cacheName:@"whatever"];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
This works fine, and results are shown in my table view. However, when pressing certain buttons I want to filter the results. So I do this:
NSPredicate *predicate = ...; //based on buttons pressed
[[self.fetchedResultsController fetchRequest] setPredicate:predicate];
[NSFetchedResultsController deleteCacheWithName:@"whatever"];
NSError * error = nil;
[self.fetchedResultsController performFetch:&error];
if (error) {
DDLogError(@"[%@ %@] fetchedResultsController ERROR: %@", THIS_FILE, THIS_METHOD, error.localizedDescription);
}
[self.myTableView reloadData];
The problem is that the table view does not reload. If I scroll the table view, the cells change based on new data, but the number of sections and rows does not change as it should each time I try to filter.
What am I missing?
Upvotes: 1
Views: 1201
Reputation: 3791
I suspect you need to insert and delete the table view rows based on your updated data.
The error message you wrote in the comments to the other answer holds the clue.
Relevant Apple documentation.
What you should specifically read is the text under the title: Batch Insertion, Deletion, and Reloading of Rows and Sections.
Before this however, as you are changing your NSFetchedResultsController
, you should check that you implement NSFetchedResultsController delegate methods to manage the changes. There is standard code available from Apple that you should consider including in your table view controller. You should not need to change / override this standard code.
See this Apple documentation.
Essentially for the "Typical Use" case you will want to implement the four typical delegate methods:
(void)controllerWillChangeContent:(NSFetchedResultsController *)controller
;(void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
;(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
;(void)controllerDidChangeContent:(NSFetchedResultsController *)controller
.In the case that you've already included these NSFetchedResultsController delegate methods, you may need to consider using the UITableView delegate methods beginUpdates
and endUpdates
with the methods:
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation: (UITableViewRowAnimation)animation;
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation: (UITableViewRowAnimation)animation;
So you should try using the following code block:
tableView.beginUpdates;
tableView.insertRowsAtIndexPaths:indexPaths withRowAnimation:animation;
tableView.deleteRowsAtIndexPaths:indexPaths withRowAnimation:animation;
tableView.endUpdates
You'll obviously need to create the arrays of indexPaths for the insert and delete methods.
Upvotes: 0
Reputation: 1023
you need to delete cache BEFORE any change to fetchResultController
From apple doc : NSFetchedResultsController Class Reference
If you are using a cache, you must call deleteCacheWithName: before changing any of the fetch request, its predicate, or its sort descriptors. You must not reuse the same fetched results controller for multiple queries unless you set the cacheName to nil.
Optionally, the name of the cache file the controller should use (passing nil prevents caching). Using a cache can avoid the overhead of computing the section and index information.
Upvotes: 1