我正在修改一些现有的笨重代码,这些代码在任何更改时只调用 [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/