【发布时间】:2018-02-14 19:20:43
【问题描述】:
我正在尝试实现一个 tableView,它有 4 个不同的可能原型单元格。它们都继承自 UITableViewCell 基类并实现其协议。
对于其中两个单元格,有异步数据获取,但特别是其中一个单元格让我很适应。流程如下:
1) 出列可重用单元
2) 调用配置
func configure(someArguments: ) {
//some checks
process(withArguments: ) { [weak self in] in
if let weakSelf = self {
weakSelf.reloadDelegate.reload(forID: id)
}
}
}
3) 如果异步数据在缓存中,请使用可用的图像/数据/资料配置单元并开心
4) 如果异步数据不在缓存中,获取它,缓存它,然后调用完成
func process(withArguments: completion:) {
if let async_data = cache.exists(forID: async_data.id) {
//set labels, add views, etc
} else {
fetch_async_data() {
//add to cache
//call completion
}
}
}
5) 如果调用了完成,则通过将索引路径向上传递到UITableViewController 并调用reloadRows(at:with:) 来重新加载有问题的行
func reload(forID: ) {
tableView.beginUpdates()
tableView.reloadRows(at: indexPath_matching_forID with: .automatic)
tableView.endUpdates()
}
现在,我的理解是 reloadRows(at:with:) 将触发另一个 dataSource/delegate 循环,从而导致一个新的可重复单元被出列,并再次调用 configure 方法,从而使步骤 #3 快乐(异步数据现在将在缓存中,因为我们刚刚获取它)。
除了……这并不总是发生。如果我的初始提取中有需要重新加载的单元格,它会起作用 - 他们获取数据并显示它。但是,有时,向下滚动到另一个需要获取的单元格不会获得正确的数据......或者更具体地说,它不会触发使用正确数据填充单元格的重新加载。我可以看到缓存正在使用新数据进行更新,但它没有...显示出来。
但是,如果我完全滚动过坏单元格,然后向上滚动,则使用正确的数据。那么,到底是什么 reloadRows?!
我尝试在 DispatchQueue.main.async 中包装各种东西,但无济于事。
reloadData 可以正常工作,但价格昂贵,因为在完全重新加载时可能会触发许多异步请求(此外,当单元格返回时,它会导致一些过度闪烁)
任何帮助将不胜感激!
【问题讨论】:
-
当“它不会触发使用正确数据填充单元格的重新加载”时,您在滚动到的单元格中究竟看到了什么?它是否显示来自另一个索引路径的一些陈旧内容?还是只是空白?
-
来自另一个索引路径的陈旧内容 - 因此,如果在第一批中有一个具有相同重用类型的单元格,它将在后面的单元格中显示该单元格的数据,不会重新填充。同样,我知道缓存已正确填充(是的打印语句),但 process(withArguments:) 方法再也不会被调用,因此它无法填写正确的数据。
-
在这种情况下,我会在
indexPath_matching_forID中查看您的逻辑。可能是针对不正确的索引路径进行了重新加载。如何将 id 关联到新的索引路径? -
在 cellForRow 中,在调用 configure 之前,我将其添加到字典
idToIndexPath[id] = indexPath并使用dataArray[indexPath.row]获取 id(它返回一个带有 id 的对象) -
打印出正在重新加载的 indexPath 后,我可以直观地确认正在使用“正确”的 indexPath。
标签: ios swift uitableview reloaddata reloadrows