Reputation: 377
Problem with NSFetchedResultsController
is that I fetched the data and it populates the UITableView
with cacheName
set to nil
. Later when I change the predicate
of NSFetchedResultsController
and called perfromFetch
, it won't refreshes the UITableView
however the data inside NSFetchedResultsController
is updated. One thing more, NSFetchedResultsControllerDelegate
methods are also not invoking.
Thanks in Advance.
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeMove:
case NSFetchedResultsChangeUpdate:
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController) {
return _fetchedResultsController;
}
NSManagedObjectContext *context = [GmailDBService sharedService].managedObjectContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Thread"];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"historyId" ascending:NO];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"SUBQUERY(messages, $m, ANY $m.labels.identifier == %@).@count > 0", self.label.identifier];
fetchRequest.sortDescriptors = @[sortDescriptor];
fetchRequest.fetchBatchSize = 20;
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
_fetchedResultsController.delegate = self;
[_fetchedResultsController performFetch:nil];
return _fetchedResultsController;
}
- (IBAction)unwindToThreadsController:(UIStoryboardSegue *)segue
{
self.fetchedResultsController.fetchRequest.predicate = [NSPredicate predicateWithFormat:@"identifier == %@", @"15f1919682399cc9"];
[self.fetchedResultsController performFetch:nil];
}
Upvotes: 0
Views: 268
Reputation: 8563
fetchedResultsController
are not expensive. You should not be afraid to create and destroy them as needed. When you need to change the predicate discard the current fetchedResultsController
and create a new one. Don't forget to reload the tableView after you do so.
The changes aren't triggering the fetchedResultsController
because you are monitoring threads, but your predicate is based on messages. So when a message is changed it does not trigger a change in the fetchedResultsController
. The controller only monitors changes to one entity and does not expect changes to other entities to effect it. You can fix this in a few ways:
fetchedResultsController
to look at message and group them by threads, then only display every section (ie thread) as a row.fetchedResultsController
is concerned).Also fetchBatchSize
isn't respected by a fetchedResultsController
so you should remove it for clarity.
Upvotes: 1