UITableView insertSections: withRowAnimation: 导致请求所有表格单元格

Posted

技术标签:

【中文标题】UITableView insertSections: withRowAnimation: 导致请求所有表格单元格【英文标题】:UITableView insertSections: withRowAnimation: causing all table cells to be requested 【发布时间】:2009-07-25 04:32:29 【问题描述】:

我正在修改一些现有的笨拙的代码,这些代码只是在任何更改上调用[tableView reloadData],以使用更具体的表更新和插入/删除方法。

但是,我在这样做时遇到了一些非常糟糕的行为。以前,正如人们想象的那样,当表格加载时,它只请求当时可见的行的单元格。这是使用reloadData 时的行为。

现在insertSections 被调用,所有 单元格在更新后被请求,可能是数百个。这导致为每一行创建单元格,完全破坏了可重用的单元格队列并且到处都是浪费。我一定做错了什么。

变化就是这么简单,导致 tableView 只要求可见行的代码:

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context 
    // ... ensure it's the right key
    [tableView reloadData];

导致 tableView 要求所有内容的代码:

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context 
    // ... ensure it's the right key
    NSUInteger sectionCount = [self sectionCount];
    NSIndexSet *indices = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, sectionCount)];
    [tableView insertSections:indices withRowAnimation:UITableViewRowAnimationFade];

我可以来回切换以查看行为变化。令人沮丧。想法?


添加赏金只是为了看看是否有人有更多见解。

beginUpdates/endUpdates 不会影响任何东西,我不希望它影响,这只是一个命令,没有什么额外的东西可以合并成一个更新。

我认为这只是渴望动画的副作用。为了让所有东西都“滑入”,它必须有所有东西来渲染。游戏结束。

【问题讨论】:

您是如何确定所有单元格都被同时请求的?没有人出队吗? 我创建了一个小型测试项目,可以重现您观察到的行为。它真的很好奇。不能单独作为动画,因为如果您指定 UITableViewRowAnimationNone,行为是相同的。如果调用 insertSections:withRowAnimation: 时插入位置不在屏幕上,则不会出现此问题。 【参考方案1】:

您似乎是在告诉表格插入所有部分,这基本上相当于重新加载。当您告诉表格它需要加载一个部分时,它需要读取该部分中的所有项目。此外,您是在 beginUpdates/endUpdates 块之外执行此操作,这意味着每次您在该部分中添加时,表都必须立即提交更改。如果您将所有内容包装在 beginUpdates/endUpdates 中,它将暂停所有查询,直到完成,这将允许系统合并冗余查询并消除不必要的查询。

您应该只在添加了新部分的情况下调用 insertSections。如果你这样做,那么 tableview 不必查询所有未更改部分的信息,即使它们四处移动。此外,如果节内的元素发生更改但节本身没有更改,则应使用方法的行版本来修改节内的那些特定行,并且只会查询这些行。

下面是一个示例(来自基于 CoreData 的应用程序),应该能够理解这一点。由于您有一个自定义模型而不是 NSFetchedResultsController,因此您必须弄清楚正在进行的操作类型,而不是仅仅检查系统传递给您的一堆常量。

//Calculate what needs to be changed     

[self.tableView beginUpdates];

for (i = 0 i < changeCount; i++) 
  type = changes[i]; 

  switch(type) 
    case NSFetchedResultsChangeInsert:
      [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                    withRowAnimation:UITableViewRowAnimationFade];
      break;

    case NSFetchedResultsChangeDelete:
      [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                    withRowAnimation:UITableViewRowAnimationFade];
      break;
  


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 configureCell:(id)[tableView cellForRowAtIndexPath:indexPath]
            atIndexPath:indexPath];
    break;

  case NSFetchedResultsChangeMove:
    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                          withRowAnimation:UITableViewRowAnimationFade];
    [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section]
                  withRowAnimation:UITableViewRowAnimationFade];
    break;
  


[self.tableView endUpdates];

【讨论】:

好吧,一点额外的信息可能会有用,这最初是一个完全空的表。我推迟了数据的加载以保持 UI 响应,所以它最初是空白的,并在它们离开网络时添加这些部分。因此,使用 reloadData 从没有部分到所有部分都可以正常工作,但是显式添加部分会导致混乱?很奇怪。 不,这是预期的,以及为什么需要 beginUpdates/endUpdates 调用来包装您正在做的事情。如果没有这些,tableView 必须假设在您所做的每次修改后都可能会影响显示,这意味着它必须查询所有部分以计算哪些单元格是可见的,然后获取所有可见的单元格。当您执行 beginUpdates 时,tableView 会停止更新,直到您调用 endUpdates,此时它可以通过查询所有中间状态来一次性完成所有操作。 “不询问你的中间状态,”我需要更多的咖啡

以上是关于UITableView insertSections: withRowAnimation: 导致请求所有表格单元格的主要内容,如果未能解决你的问题,请参考以下文章

UITableView insertSections: withRowAnimation: 导致请求所有表格单元格

UICollectionView insertSections 错误 - NSInvalidArgumentException 原因 setObjectForKey 对象不能为 nil UIColle

滚动时将部分插入 UICollectionView 时的性能问题

连接 UITableView + UITableView

将 UITableView 推送到 UITableView

UItableview 单元格的动态高度与 UItableview 单元格内的 UItableview