简体   繁体   中英

Images in UITableViewCell change after scrolling down and back up

I have a picture and some labels inside my cells. If I have more cells than what can fit on the page, scrolling down then back up loads a different image momentarily then loads the original photo. I have read around StackOverflow to see what would work in my case, but so far I can't find anything since my UITableView is inside a ViewController.

Here is how I load my content into my cell:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! PostTableViewCell
    // Configure the cell...
    let post = self.posts[indexPath.row] as! [String: AnyObject]
    cell.titleLabel.text = post["title"] as? String
    cell.priceLabel.text = post["price"] as? String
    if let imageName = post["image"] as? String {
        let imageRef = FIRStorage.storage().reference().child("images/\(imageName)")
        imageRef.data(withMaxSize: 25 * 1024 * 1024, completion: { (data, error) -> Void in if error == nil {
            let image = UIImage(data: data!)
            UIView.animate(withDuration: 0.4, animations: {
                cell.titleLabel.alpha = 1
                cell.postImageView.alpha = 1
                cell.priceLabel.alpha = 1
            cell.postImageView.image = image
            })
        } else {
            print("Error occured during image download: \(error?.localizedDescription)")
            }
        })
    }
    return cell
}

Is there any way I could change tableView.dequeueReusableCell to something different so this doesn't happen?

In your table view cell PostTableViewCell you need to implement the method

 override func prepareForReuse() {
    super.prepareForReuse()
    self.postImageView.image = nil
    // Set cell to initial state here, reset or set values
}

The cells are holding on to their old content

I think you run into problems because you update the cell inside the completion block. If the cell scrolls out of view before the completion block is run, it'll be reused for a different row, but you're still setting the image for the previous row.

Try this:

imageRef.data(withMaxSize: 25 * 1024 * 1024, completion: { (data, error) -> Void in if error == nil {
        if let cell = self.tableView.cellForRow(at: indexPath) as? PostTableViewCell {
            let image = UIImage(data: data!)
            UIView.animate(withDuration: 0.4, animations: {
                cell.titleLabel.alpha = 1
                cell.postImageView.alpha = 1
                cell.priceLabel.alpha = 1
                cell.postImageView.image = image
            }
        })

Instead of relying on the cell still being visible, this will try to get it from the table view based on indexPath . If it's not visible any more, cellForRow(at:) will return nil .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM