Вопрос проверяет понимание жизненного цикла асинхронных операций и их несинхронизированность с UI.
Асинхронный запрос живет дольше, чем конфигурация ячейки. Когда запрос стартовал, ячейка была связана с одними данными, но к моменту завершения она уже может использоваться для других. Запрос при этом не отменяется автоматически. Он возвращает результат и обновляет UI без знания текущего состояния. В итоге старый результат применяется к новой ячейке.
Асинхронные операции не привязаны к жизненному циклу UICollectionViewCell и выполняются независимо.
Важно понимать, что жизненный цикл ячейки и сетевого запроса — разные процессы.
Ячейка может переиспользоваться за миллисекунды
Запрос может выполняться сотни миллисекунд
UIKit не синхронизирует эти процессы
Из-за этого результат запроса может прийти в неподходящий момент.
Запрос не знает:
К какой модели он относится сейчас
Актуальна ли ячейка
Нужно ли еще применять результат
Он просто вызывает completion.
loadImage { image in
cell.imageView.image = image
}
В этом коде отсутствует проверка актуальности ячейки.
Если результат асинхронного запроса не проверяется на актуальность, он может попасть в переиспользованную ячейку. Это нормальное поведение системы, а не баг UIKit.