提问人:Madhu 提问时间:10/12/2023 更新时间:10/13/2023 访问量:71
面临 cellForRowAt 中的 indexPathsForVisibleRows 问题
Facing issue with indexPathsForVisibleRows in cellForRowAt
问:
我正在显示来自 url 的图像并用于缓存,它按预期工作。我现在面临的唯一问题是在非常快速地滚动 UITableView 的同时下载图像时,在某些时候滚动时,我检查 visibleRows 的 if 条件失败,因此在下载图像后重新加载特定单元格不会发生,因此单元格显示占位符图像。并非每张图像都会发生这种情况,在快速滚动时仅观察到几张图像的问题,图像 url 没有问题,如果我来回滚动,会再次加载相同的图像。由于在单元格可见之前加载,因此条件失败。如何确保快速滚动时条件不会失败UITableView
SDWebImage
cellForRowAt
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: TableViewCell) as? TableViewCell else {
// fall back code
}
//code to get the url from userData object
let imageUrl = userData.imagePath
//if the image is not in the cache download it
guard let _ = SDImageCache.shared.diskImageData(forKey: imageUrl) else {
if let url = URL(string: imageUrl) {
SDWebImagePrefetcher.shared.prefetchURLs([url], progress: nil) { [weak self] (_, _) in
guard let self = self else { return }
// i am facing using with this if condition sometimes the if condition is returning false
if let visibleRows = self.tableView.indexPathsForVisibleRows, visibleRows.contains(indexPath) {
self.tableView.reloadRows(at: [indexPath], with: .none)
}
}
}
cell.setNeedsLayout()
return cell
}
}
我在里面设置图像,所以我只需要触发 reloadRows 以便显示下载的图像。CustomTableViewCell
注意:中的代码没有问题,问题仅出在里面的 if 条件上,如果我删除 if 条件,那么它就可以正常工作并且能够正确查看所有图像,但重新加载不可见的单元格会影响性能。CustomTableViewCell
cellForRowAt
尝试以下解决方案
- 在主线程中运行代码
- 添加代码
willDisplay cell:
没有任何效果,需要一个解决方案来避免条件失败。任何意见将不胜感激。
答:
您面临的问题似乎是,下载映像后,您只会更新可见的单元格,而不会更新准备好的单元格。
对于某些单元格,您遇到的是下载是由方法触发的。然后这个单元格离开屏幕(或保持在屏幕之外),但处于所谓的“准备”状态。下载完成后,您不会更新单元格,因为它不可见。当您滚动到单元格时,它不会按方法更新,因为没有为准备好的单元格调用此方法。tableView:cellForRowAt
tableView:cellForRowAt
我可以想象这种情况发生的可能性很小,调试起来也很痛苦。
幸运的是,您可以使用方法检测可见细胞和制备的细胞。此方法不会使单元格出列,也不会执行任何其他复杂逻辑。它只是返回一个单元格,该单元格已注册为可见或已准备好,否则为 。tableView.cellForRow(at: indexPath)
nil
请尝试以下操作来解决此问题:
if self.tableView.cellForRow(at: indexPath) != nil {
self.tableView.reloadRows(at: [indexPath], with: .none)
}
评论
if
.reloadRows(at: [indexPath], with: .none)
myData[4]
tableView.reloadRows(at: [IndexPath(row: 4, section: 0)], with: .none)
cellForRowAt
cellForRowAt
cellForRowAt
.reloadRows(at: [indexPath], with: .none)
cellForRowAt
cellForRowAt
评论
if self.tableView.cellForRow(at: indexPath) != nil