Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableView cell is displaying an incorrect image, even while setting the image to nil as the first step in tableView.dequeueReusableCell

I'm trying to do something very basic, but the fix proposed in other similar questions does not seem to be working. I have an image cache, and a tableView. I want to display the image from the cache if it exists, otherwise there should be nothing. For some reason the tableView is still displaying a reused cell with the wrong image, even when I set the image view to nil. Below is my code:

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

    cell.profilePhoto?.image = nil
    cell.profilePhoto?.backgroundColor = UIColor.gray
    if let userID = myObject.posterId, let profileImage = self.imageCache.object(forKey: userID as AnyObject) {
        cell.profilePhoto?.image = profileImage
    } else {
        if let userId = myObject.posterId {
            downloadImage.beginImageDownload() {
                (imageOptional) in
                if let image = imageOptional {
                    cell.profilePhoto?.image = image
                    self.imageCache.setObject(image, forKey: userId as AnyObject)
                }
            }
        }
    }

What am I doing wrong? I can't for the life of me figure out why the image is not being set to nil, even though I do that as the first step!

like image 818
Josh Avatar asked Mar 21 '17 00:03

Josh


1 Answers

The problem is downloadImage.beginImageDownload closures are holding references to the uitableview cells.

When you complete the image download, you set cell.profilePhoto?.image property, even if the tableView recycles reusable cells to display a different row.

Assign your cell's tag to the indexPath.row and test if cell is still relevant for assigning downloaded image:

/* right after cell dequeue */
cell.tag = indexPath.row

then

/* download finished here */
if cell.tag == indexPath.row {
    /* yeah, I want to rock this cell with my downloaded image! */
    cell.profilePhoto?.image = downloadedImage
}

Be aware: this will only work in tableview with one section.

P.S. You can place the clean up of your cells in prepareForReuse method inside the SearchResultsTableViewCell to tidy things a little.

like image 89
Oleh Zayats Avatar answered Nov 02 '22 07:11

Oleh Zayats