UITableView 的 reloadRowsAtIndexPaths: (NSArray *) indexPaths 无法导致重新加载,除非你调用它两次?

Posted

技术标签:

【中文标题】UITableView 的 reloadRowsAtIndexPaths: (NSArray *) indexPaths 无法导致重新加载,除非你调用它两次?【英文标题】:UITableView's reloadRowsAtIndexPaths: (NSArray *) indexPaths failing to cause a reload unless you call it twice? 【发布时间】:2011-07-30 06:34:38 【问题描述】:

我有一个 UITableViewController 管理 iPad 应用程序中的 UITableView 对象。表格视图与相当复杂的其他对象群联系在一起。当我要求它重新加载一行时,我遇到了问题,如下所示:

//indexPath is an NSIndexPath with indexes 0 and 0.  At the moment, this is the only cell in the table view.
NSArray *array = [NSArray arrayWithObject:indexPath]; 
[self.tableView reloadRowsAtIndexPaths:array withRowAnimation:UITableViewRowAnimationNone]; 

问题是该行没有重新加载。永远不会有对 cellForRowAtIndexPath 的回调。

疯狂的是,如果我调用 reloadRowsAtIndexPaths 两次,第二次调用确实会触发重新加载:

//indexPath is an NSIndexPath with indexes 0 and 0.  At the moment, this is the only cell in the table view.
NSArray *array = [NSArray arrayWithObject:indexPath]; 
[self.tableView reloadRowsAtIndexPaths:array withRowAnimation:UITableViewRowAnimationNone];   // does not reload
[self.tableView reloadRowsAtIndexPaths:array withRowAnimation:UITableViewRowAnimationNone];   // does reload

我想知道是否有其他人遇到过这样的错误,如果有,原因是什么?

【问题讨论】:

你是在后台线程中这样做的吗? 主线程。如果“测试用例”是指一个简单的例子来说明同样的事情,不,我没有,我希望我有。 遇到同样的问题,我使用的是 Xcode 6.3.2 和 swift 1.2,无法从一次调用中重新加载某行。几乎尝试了所有方法,但单元格仅从第二个连续的 reloadRowsAtIndexPaths 调用中刷新。 有解决办法吗? 【参考方案1】:

reloadRowsAtIndexPaths:... 仅在封装在调用之间时有效:

- (void)beginUpdates;
- (void)endUpdates;

除此之外,行为是未定义的。 (正如您所发现的,相当不可靠)。

编辑:引用“iPhone OS Table View Programming Guide”的相关部分:

要对行和部分的批量插入和删除进行动画处理,请在由连续调用 beginUpdates 和 endUpdates 定义的动画块中调用插入和删除方法。如果你不调用这个块内的插入和删除方法,行和节的索引可能是无效的。 beginUpdates...endUpdates 块不可嵌套。

在一个块结束时——即在 endUpdates 返回之后——表视图查询它的数据源并像往常一样为行和节数据进行委托。因此,支持 table view 的集合对象应该更新以反映新的或删除的行或节。

在 iPhone OS 3.0 中引入的 reloadSections:withRowAnimation: 和 reloadRowsAtIndexPaths:withRowAnimation: 方法与上面讨论的方法相关。它们允许您请求表视图重新加载特定部分和行的数据,而不是通过调用 reloadData 来加载整个可见表视图。

【讨论】:

去年这个问题让我死了一个星期......它确实说,但它隐藏在表格视图编程指南中,而不是参考文档中。 添加了苹果文档中的相关部分。他们提到“与上面讨论的方法有关”这是对英语的相当模棱两可的使用,但实际上这意味着 reloadRows... 仅适用于 beginUpdates 和 endUpdates 之间。 我试着把它包起来。仍然是相同的行为。然后我按照您的建议将我的 earlier 调用之一打包到 reloadData 。这解决了它。 很高兴你解决了它。有点好奇,因为 reloadData 是唯一不需要用 begin/endUpdates 包装的 reloadXXX 方法... 看来我弄错了,那里还有第二次重新加载。仍在搜索中 。 . .【参考方案2】:

我知道这个话题有点老了,但我遇到了同样的问题和一个简单的修复。我有一个表格视图,当我调用 reloadData 和/或 reloadRowsAtIndexPaths 时,tableview 方法 cellForRowAtIndexPath 不会触发。 事实证明,我没有在 Interface Builder 中连接我的 tableview IBOutlet - 一旦连接了所有按预期触发的东西。总是那些小事... 此外,就像其他人提到的那样,如果您只需要一个调用,则不需要将其包装在 begin/endUpdates 中。

【讨论】:

以上是关于UITableView 的 reloadRowsAtIndexPaths: (NSArray *) indexPaths 无法导致重新加载,除非你调用它两次?的主要内容,如果未能解决你的问题,请参考以下文章

水平 UITableView 中的垂直 UITableView

将 UITableView 推送到 UITableView

如何与重叠显示的 UITableView 交互另一个 UITableView

UITableView

iOS小技能:1. 什么是UITableView? 2. UITableView如何展示数据

UITableView 优化总结