问题
Within SO there are a lot of questions/replies about NSFetchedResultsController
and delegate. Sometimes the delegate fires, sometimes not. And since Core Data is quite complex argument is quite difficult to understand what is going on without spending a lot of time on it. In addition, the documentations says that there are several problems but it does not list them.
There are several known issues and behavior changes with NSFetchedResultsController on various releases of iOS.
Hence, I need some clarifications about the behavior of such a class. In particular, from the documentation there is written the following:
A controller thus effectively has three modes of operation, determined by whether it has a delegate and whether the cache file name is set.
No tracking: the delegate is set to nil. The controller simply provides access to the data as it was when the fetch was executed.
Memory-only tracking: the delegate is non-nil and the file cache name is set to nil. The controller monitors objects in its result set and updates section and ordering information in response to relevant changes.
Full persistent tracking: the delegate and the file cache name are non-nil. The controller monitors objects in its result set and updates section and ordering information in response to relevant changes. The controller maintains a persistent cache of the results of its computation.
I'm developing a quite complex app and I'm taking advantage of NSFetchedResultsController
to retrieve data from a store and display them in a table.
Displayed managed objects have a syncStatus
boolean variable to verify if they have been synced with an external service or not. syncStatus
variable is not displayed in a cell, different info are displayed (e.g. text values). In other words, syncStatus
is not fired as fault.
In the table, by means of NSFetchedResultsController
, I display the only elements that are not synced (the bool value is set to NO
).
- (NSFetchedResultsController*)fetchedResultsController
{
if(_fetchedResultsController)
return _fetchedResultsController;
NSManagedObjectContext* mainContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"LocalEntity" inManagedObjectContext:mainContext]];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"syncStatus == %@", [NSNumber numberWithBool:NO]]];
[fetchRequest setFetchBatchSize:10];
// sort descriptor here...
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:mainContext sectionNameKeyPath:nil cacheName:nil];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
The user can select the elements she/he wants to sync and a background thread sends the selected elements to the service and, for those, it also changes the syncStatus
variable to YES
.
When the operation is finished, since I set the NSFecthedResultsControllerDelegate
and I register for NSManagedObjectContextDidSaveNotification
(I also merge in the main thread the changes through the notification. I'm able to see that the notification contains objects with the correct change), I expect the table is updated (the objects with syncStatus
set to YES
would be not displayed).
Said this, the question is the following.
Based on doc, since I use the Memory-only tracking option, does the missing update is due to the fact isSyncStatus
is not loaded on memory but it remains a fault?
Could you suggest me in the right direction?
Thank you in advance.
P.S.
NSFetchedResultsControllerDelegate
methods are implemented correctly. Doing the same only in main thread works.
回答1:
Are you implementing the NSFetchedResultsControllerDelegate
methods to remove the cell?
- (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 NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
来源:https://stackoverflow.com/questions/13527133/needed-clarifications-for-nsfetchedresultscontroller-and-nsfetchedresultscontrol