Swift中UITableViewCell图片重复,常用解决方案无效该如何处理
问题根因
你已做的复用重置逻辑没有问题,图片重复的核心原因是异步图片请求的回调没有做身份校验:当cell被快速滑动复用于其他行数据时,上一个绑定关系触发的图片请求完成后,仍会把旧图片赋值到已经被复用的cell上,直接覆盖了你在prepareForReuse里的置空操作。
修复方案
第一步:为自定义Cell增加标识属性
在EmployeeTableViewCell中新增属性记录当前绑定的员工ID,用于请求回调的身份校验:
@IBOutlet weak var profileImage: UIImageView! // 新增:记录当前cell绑定的员工ID var currentEmployeeID: String? override func awakeFromNib() { super.awakeFromNib() } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) } override func prepareForReuse() { super.prepareForReuse() self.profileImage.image = nil // 复用的时候清空绑定标识 self.currentEmployeeID = nil }
第二步:修改cellForRowAt的图片加载逻辑
每次请求图片前先记录当前cell对应的员工ID,图片请求回调返回时,先判断返回的ID是否和当前cell绑定的ID一致,不一致直接丢弃回调结果:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: EmployeeTableViewCell.self), for: indexPath) as! EmployeeTableViewCell let employee = directoryPresenter!.getEmployeeItem(position: indexPath.row) cell.onBindCell(employee: employee) // 先直接设置占位图,避免等待期间出现空白或者旧图残留 cell.profileImage.image = UIImage(named: "placeholder_profile_male") // 记录当前cell绑定的员工ID let targetEmployeeID = employee.employeeID cell.currentEmployeeID = targetEmployeeID directoryPresenter!.getProfileImage(id: targetEmployeeID) { image in // 校验:如果当前cell绑定的ID已经不是请求的ID,说明cell已经被复用,直接返回 guard cell.currentEmployeeID == targetEmployeeID else { return } if let image = image { cell.profileImage.image = image } else { cell.profileImage.image = UIImage(named: "placeholder_profile_male") } } cell.actionCallBack = self return cell }
可选优化点
如果你的getProfileImage方法没有做请求取消逻辑,可以进一步在cell的prepareForReuse方法中取消当前cell未完成的图片请求,减少无用的网络开销。
内容的提问来源于stack exchange,提问作者Thejani Saranaguptha
相关产品推荐
相关产品推荐

