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

时间:2009-07-25 04:32:29

标签: iphone objective-c uitableview uikit

我正在修改一些现有的严厉代码,只要在任何更改时调用[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不影响任何东西,我不指望它,这只是一个命令,没有什么额外的东西可以合并到一个更新中。

我认为这只是想要动画的副作用。要让所有内容“滑动”,它必须拥有一切要呈现的内容。游戏结束。

1 个答案:

答案 0 :(得分:6)

看来你正在告诉表插入所有部分,这基本上等同于重新加载。当你告诉表它需要加载一个部分时,它需要读取该部分中的所有项目。此外,您在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];