iphone - UITableView insertSections : withRowAnimation: causing all table cells to be requested

标签 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 不会影响任何东西,我不希望它影响,这只是一个命令,没有任何额外的东西可以合并到一个更新中。

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

最佳答案

看来您是在告诉表格插入所有部分,这基本上等同于重新加载。当您告诉表它需要加载一个部分时,它需要读取该部分中的所有项目。此外,您是在 beginUpdates/endUpdates block 之外执行此操作,这意味着每次您在该部分中添加时,表都必须立即提交更改。如果您将所有内容都包装在 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];

关于iphone - UITableView insertSections : withRowAnimation: causing all table cells to be requested,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1181206/

相关文章:

ios - UIButton 子类中的 imageview.transform 奇怪行为

像 iMessage 一样的 iOS 消息 View 控件

进入前台时(在后台一段时间后)iOS 7 应用程序崩溃(包括崩溃日志)

objective-c - 全局变量作为单例的别名?

ios - didReceiveRemoteNotification 在 Firebase 与 Push 框架一起使用时未调用

jquery - 使用 jquery.on ('click' 时 iPhone 上的元素闪烁

ios - 如何将 FMDB 导入 swift 框架

ios - 单击 uitableviewcell 时推送 View

uitableview - iOS 7 - 如何在表格 View 中显示日期选择器?

ios - Autolayout 动态高度 TableView 单元格在文本更改时呈现错误