Swift Firestore UITableView cellForRowAt中downloadURL闭包cell引用错误问题
UITableView异步下载Storage资源时cell引用错乱问题解析
触发原因
这个问题是UITableView cell复用机制和异步网络请求的回调时机不确定性共同导致的:
- UITableView为了性能优化会复用滚出屏幕的cell,当你调用
reloadData刷新列表、或者滚动列表时,旧cell会被回收赋值给新的indexPath使用,此时你给cell设置的tag也会被覆盖为新的indexPath.row。 - Firestore Storage的
downloadURL是异步方法,发起请求后不会立刻执行回调,回调会在网络请求完成后才触发。如果请求还没完成时cell已经被复用,之前的旧请求回调捕获的indexPath还是原来的旧行号,但此时cell已经属于新的indexPath,tag也已经被修改,就会出现打印的indexPath.row和cell.tag不匹配的问题。
修复方案
方案1:回调时校验cell是否还属于当前indexPath
在异步回调里先判断cell的tag是否和当前请求对应的行号一致,不一致就直接丢弃本次请求结果,避免给复用后的cell赋值错误内容:
guard let cell = tableView.dequeueReusableCell(withIdentifier: "venuepostcell") as? VenuePostTableViewCell else { return UITableViewCell()} let targetRow = indexPath.row cell.tag = targetRow sRef.downloadURL { downloadURL, error in // 校验cell未被复用,否则直接返回 guard cell.tag == targetRow else { return } if let downloadURL = downloadURL { print ("=== A \(targetRow) \(cell.tag)") // 后续给cell设置图片等业务逻辑写在这里 } }
方案2:cell复用时取消未完成的旧请求
自定义cell类,在复用前取消绑定在cell上的旧下载任务,从根源避免无用回调执行:
- 先给VenuePostTableViewCell添加下载任务存储属性和复用逻辑:
import FirebaseStorage class VenuePostTableViewCell: UITableViewCell { // 存储当前cell绑定的下载任务 var currentDownloadTask: StorageDownloadTask? // 可按需添加显示图片的控件属性 @IBOutlet weak var contentImageView: UIImageView! override func prepareForReuse() { super.prepareForReuse() // 复用前取消旧请求,重置UI currentDownloadTask?.cancel() currentDownloadTask = nil contentImageView.image = UIImage(named: "placeholder") // 替换为你的占位图 } }
- 在cellForRowAt中存储下载任务:
guard let cell = tableView.dequeueReusableCell(withIdentifier: "venuepostcell") as? VenuePostTableViewCell else { return UITableViewCell()} cell.tag = indexPath.row // 把下载任务存到cell的属性中 cell.currentDownloadTask = sRef.downloadURL { [weak cell] downloadURL, error in guard let cell = cell else { return } if let downloadURL = downloadURL { print ("=== A \(indexPath.row) \(cell.tag)") // 后续业务逻辑 } }
方案3:使用成熟的图片加载框架
直接使用Kingfisher、SDWebImage这类业内通用的图片加载库,这类库已经内置了cell复用校验、请求自动取消、多级缓存的能力,不需要手动处理复用冲突,开发效率和稳定性更高。
内容的提问来源于stack exchange,提问作者justdan0227
相关产品推荐
相关产品推荐

