tableView cellForRowAt indexPath


#1

Добрый вечер.
У меня какая то странная проблема)
Есть tableView, есть ячейка, в ней imageView, при загрузке изображений происходит чередование загруженных изображений, хотя по идее до загрузки imageView должен быть пустым.

let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! HousesTableViewCell

        if let imageURL = URL(string: "http://www.../\(Houses[indexPath.item].Image)"){
            backgroundOperationQueue.addOperation {
                let data = try? Data(contentsOf: imageURL)
                if let data = data {
                    let image = UIImage(data: data)
                    DispatchQueue.main.sync {
                        cell.imageLabel.image = image
                    }
                }
            }
        }

return cell

Логики при загрузке вообще никакой не обнаружил…


#2

Логика простая :slight_smile:
Вы загрузили картинку в ячейку, скроллите, старая ячейка пропадает, выезжает новая с той же картинкой - так происходит потому что tableview использует количество ячеек которое помещается на экран, при скролле они переиспользуются.
При асинхронной загрузки ещё интересней, при объявлении замыкание захватывает ячейку с одним индексом (во время появления ячейки на экране), вы при этом яростно сроллите (ячейки меняются местами) и позже когда выполняется код в замыкании (после загрузки картинки) у захваченной ячейки уже совершенно другой индекс, соответственно по нужному индексу совершенно другая ячейка, не та что захватило замыкание.

По этому, удаляйте старую картинку и ищите ячейку по indexPath:

let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! HousesTableViewCell
cell.imageLabel.image = nil

if let imageURL = URL(string: "http://www.../\(Houses[indexPath.item].Image)"){
    backgroundOperationQueue.addOperation {
        let data = try? Data(contentsOf: imageURL)
        if let data = data {
            let image = UIImage(data: data)
            DispatchQueue.main.sync {
                if let cell = tableView.cellForRow(at: indexPath) as? HousesTableViewCell {
                    cell.imageLabel.image = image
                }
            }
        }
    }
}
return cell

#3

Большое спасибо за помощь и разъяснение! :+1:

Получается что ячейка переиспользуется только после загрузки изображения, это и было видно при скроллинге, но понять было невозможно) Как сейчас понимаю лучшим решением так же будет дополнительная загрузка изображений в память, поскольку NSCache сохраняет объекты только в рамках одной сессии.