Исправьте таблицу, где при быстрой прокрутке строки на миг показывают чужую картинку
Лента-таблица грузит аватар каждой строки асинхронно. При быстрой прокрутке строки на миг показывают чужую картинку, прежде чем исправиться. Определите причину и исправьте так, чтобы ячейка никогда не показывала картинку, предназначенную другой строке.
Ограничения:
- Сохраните переиспользование — не отключайте
dequeueReusableCell. - Отмените или игнорируйте устаревшую загрузку; не зовите
reloadDataна каждом завершении.
func tableView(_ tv: UITableView, cellForRowAt ip: IndexPath) -> UITableViewCell {
let cell = tv.dequeueReusableCell(withIdentifier: "Cell", for: ip)
let url = items[ip.row].avatarURL
ImageLoader.load(url) { image in
cell.imageView?.image = image // ложится на ту строку, что сейчас в ячейке
}
return cell
}
Найдите и исправьте ошибку.
Замыкание захватывает переиспользуемую ячейку, отданную другой строке раньше прихода картинки, поэтому рисуется чужой аватар. Сбросьте картинку в prepareForReuse и в завершении сверьте URL ячейки, иначе отбросьте устаревшую загрузку.
- ✗Винят нестабильность
IndexPathвместо переработки ячеек - ✗Чинят отключением переиспользования вместо защиты завершения
- ✗Забывают сбросить картинку до старта async-загрузки
- →Как токен загрузки на ячейку позволяет игнорировать устаревшее завершение?
- →Почему сброс в
prepareForReuseбез отмены всё равно оставляет мигание?
Ячейку перерабатывают до прихода картинки, поэтому завершение пишет аватар в ячейку, уже показывающую другую строку. Свяжите завершение с запрошенным URL и сбрасывайте картинку до загрузки:
final class AvatarCell: UITableViewCell {
private var loadingURL: URL?
override func prepareForReuse() {
super.prepareForReuse()
imageView?.image = nil // сброс старого состояния
loadingURL = nil
}
func configure(_ url: URL) {
imageView?.image = nil
loadingURL = url
ImageLoader.load(url) { [weak self] image in
guard let self, self.loadingURL == url else { return } // всё ещё та строка?
self.imageView?.image = image
}
}
}
loadingURL работает как токен: устаревшее завершение видит несовпадение и выходит, а prepareForReuse чистит ячейку заранее, так что чужой картинке неоткуда взяться.