为什么我的UITableView重新加载其所有节标题?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么我的UITableView重新加载其所有节标题?相关的知识,希望对你有一定的参考价值。

我正在开发用于管理用户任务的应用程序。该应用程序列出了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];
}

我有两个问题:

  1. 性能问题:UITableView似乎在一对beginUpdates / endUpdates之后重新加载整个部分数据。它再次询问数据源的节数,节标题和每个节中的行数。 (但是,它不会再次询问所有单元格,只要它们已经更改。)因为我的节标题显示了上面提到的字符串以及日期和任务数量,这是一个性能问题,因为标题是由NSDateFormatter和核心数据计数查询的组合。
  2. 理解问题:在一对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个或更多部分的表,也可以获得合理的性能。

以上是关于为什么我的UITableView重新加载其所有节标题?的主要内容,如果未能解决你的问题,请参考以下文章

UITableView 重新加载时闪烁

UITableview 不重新加载和刷新

UITableView 重新加载

避免重新加载 UITableView 数据

解析查询后在哪里重新加载 UITableView 数据

当 deviceOrientation 改变时在 UITableView 中重新加载数据