我正在开发用于管理用户任务的应用程序。该应用程序列出了UITableView
中的任务。一天的任务分为一个部分。部分标题显示当天的日期和任务数:
2014/05/03 - (42项任务)
NSFetchedResultsController
监控实体'任务'。当用户插入新任务时,系统会要求他提供日期,时间,描述等详细信息。 FRC识别插入或更改属性并调用委托方法:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
switch(type)
{
case NSFetchedResultsChangeInsert:
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeMove:
[self.tableView deleteRowsAtIndexPaths:[NSArray
arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.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;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
}
我有两个问题:
UITableView
似乎在一对beginUpdates
/ endUpdates
之后重新加载整个部分数据。它再次询问数据源的节数,节标题和每个节中的行数。 (但是,它不会再次询问所有单元格,只要它们已经更改。)因为我的节标题显示了上面提到的字符串以及日期和任务数量,这是一个性能问题,因为标题是由NSDateFormatter
和核心数据计数查询的组合。beginUpdates
/ endUpdates
之后,UITableView
总是要求两次剖面数据!这意味着它连续两次询问有多少部分,每个部分的标题两次,但每个部分的行数只有一次:
1对beginUpdates / endUpdates触发器:
2x numberOfSectionsInTableView
2x tableView:titleForHeaderInSection:
1x tableView:numberOfRowsInSection:遗憾的是,在beginUpdates和endUpdates中操作表之后,UITableView将为表中的每个部分调用numberOfRowsInSection:和titleForHeaderInSection:这是很准确的。
对于具有大量节而且每个节没有多行的表,这消除了删除/插入行而不是仅调用reloadData的许多优点。据我所知,除了实现自己的自定义tableview之外,没有办法避免所有这些委托调用。
也就是说,您可以通过删除titleForHeaderInSection:的实现来提高性能。可以在委托的viewForHeaderInSection:中实现相同的功能,只有在屏幕上显示的部分才会调用它。这可以减少数千次调用titleForHeaderInSection对一些对viewForHeaderInSection的调用。结合快速预缓存每个部分中的行数的策略,即使对于具有10,000个或更多部分的表,也可以获得合理的性能。