问题
I have a UITabbar
with multiple controllers in it. One of the controllers is used to add Events to Core Data, while another controller is used to display events as in a UITableView using NSFetchedResultsController
.
Here's the behaviour that I would like to achieve:
Upon disappearing, the UITableView stops updating, and when the user comes back, the entire table view is reloaded. Otherwise, inserting events from the other controller takes longer, as new rows are created in the UITableView
, even thought it is not visible.
I'm wondering how I can achieve this behavior, as it doesn't seem to work as I expect it would be:
I have set the delegate of the NSFetchedResultsController to nil in viewWillDisappear
, and restore it in viewWillAppear
, along with a call to [UITableView reloadData]
;
Somehow, I do not see the new data, and suspect this is due to the way NSFetchedResultsController stops fetching if it does not have a delegate.
How can I properly "suspend" updates to UITableView
when it disappears, but still able to see the entire dataset when the controller reappears?
回答1:
Try sending performFetch:
to the NSFetchedResultsController
in viewWillAppear:
after you have set its delegate back to self
.
回答2:
I think you do not have to "suspend" the table view updates. A UITableView
will anyway only request data from the NSFetchedResultsController
for visible cells. If the the table view is not visible, no updates will be fired.
Did you test if inserting events from another controller really takes longer? I doubt it. What does Instruments say?
If your delegate methods are fired, you could still check if the table view is visible before doing any updates.
After that, you do exactly as suggested by rob: do a performFetch:
in viewWillAppear:
.
回答3:
Instead of setting the delegate
of the NSFetchedResultsController
to nil in viewWillDisappear
, try setting an object of NSFetchedResultsController
to nil
回答4:
What about this crude approach? Not tested it.
@property (nonatomic) BOOL bruteForceReload;
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.bruteForceReload = NO;
}
-(void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
self.bruteForceReload = YES;
}
-(void)setBruteForceReload:(BOOL)bruteForceReload {
_bruteForceReload = bruteForceReload;
if (_bruteForceReload) {
[self.tableView reloadData];
}
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
if (!self.bruteForceReload) {
[self.tableView beginUpdates];
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
if (!self.bruteForceReload) {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
default:
return;
}
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
if (!self.bruteForceReload) {
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
if (!self.bruteForceReload) {
[self.tableView endUpdates];
} else {
[self.tableView reloadData];
}
}
来源:https://stackoverflow.com/questions/13187126/how-to-prevent-nsfetchedresultscontroller-from-updating-tableview-when-the-contr