如何在UITableView单元格中重新加载SDWebImage异步加载的UIImage
解决SDWebImage在UITableView中异步加载图片不及时刷新的问题
核心问题分析
你原代码的错误在于使用了全局的itemImage对象加载图片,再将其赋值给cell的imageView。这种做法完全违背了UITableView的cell复用机制:
- 异步加载图片时,cell已经被返回并显示,
itemImage的后续更新无法同步到对应的cell; - 直接赋值
cell.imageView?.image = itemImage.image时,异步请求还未完成,只能拿到占位图,只有当cell被复用重新执行cellForRowAt时,才可能读取到缓存的图片。
正确解决方案
直接使用cell自带的imageView调用SDWebImage的sd_setImage方法,SDWebImage内部已经处理了异步加载完成后的UI更新,以及cell复用场景下的图片匹配问题,无需手动调用表格刷新:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) let item = items[indexPath.row] // 直接操作cell的imageView,无需全局变量 if let url = URL(string: item.stringUrl) { let placeholderImage = UIImage(named: "noPhoto.png") cell.imageView?.sd_setImage(with: url, placeholderImage: placeholderImage) } else { // URL无效时,手动设置占位图 cell.imageView?.image = UIImage(named: "noPhoto.png") } cell.textLabel?.text = item.title cell.detailTextLabel?.text = "item id: \(item.id)" return cell }
为什么之前的尝试无效
- 调用
reloadData():每次图片加载完成都刷新整个表格,不仅性能损耗大,还会强制表格回到顶部,完全破坏滚动体验; - 调用
reloadRows(at:):异步加载完成后,原indexPath对应的cell可能已经被复用给其他行,此时刷新原indexPath会触发cell重新初始化,加上SDWebImage的缓存状态未同步,就会出现图片随机显示或隐藏的异常。
内容的提问来源于stack exchange,提问作者Bartolomeo
相关产品推荐
相关产品推荐

