IOS tableview reuse old images when loading new images

I read a similar post in the old reusable image showing and I am still getting the same problems. Basically I have a TableView that loads images from amazon s3 when scrolling down, everything works well until you reach the 12th or 13th image. It happens that the image in line before appearing on a new line for about 2 seconds when loading a new image. This is my code (I'm still new to quick and learning IOS). stream_image_string as a full url to download images and PicHeight is an integer stored with the image height as each image usually has a different height.

var Stream_Cache = NSCache<AnyObject, AnyObject>()
  var stream_image_string = [String]()
    var PicHeight = [Int]()

      

This is inside the UITableViewCell, first I check if there is a url that will be more than 0 characters long. Then I check if the image / url is stored in the cache, if not then I will load it.

            if stream_image_string[indexPath.row].characters.count > 0 {
        if let image = Stream_Cache.object(forKey: stream_image_string[indexPath.row] as AnyObject) as? UIImage {
              DispatchQueue.main.async(execute: { () -> Void in
            cell.stream_image.image = image


            })
        } else {
            if cell.stream_image != nil {
            let strCellImageURL = self.stream_image_string[indexPath.row]
            let imgURL: NSURL = NSURL(string: strCellImageURL)!
        let request:NSURLRequest =  NSURLRequest(url: imgURL as URL)
        let config = URLSessionConfiguration.default
        let session = URLSession(configuration: config)

      cell.Stream_Image_Height.constant = CGFloat(Float(cell.pic_height!))
        let task = session.dataTask(with: request as URLRequest,    completionHandler: {(data, response, error) in
            DispatchQueue.main.async(execute: { () -> Void in

                if data != nil {
                cell.stream_image.image = UIImage(data: data!)
                } else {
                     cell.Stream_Image_Height.constant = 0
                    cell.stream_image.image = nil
                }


            })
        });

        task.resume()
            }
    }
    } else {

        cell.Stream_Image_Height.constant = 0
    }

      

In my UITableViewCell file, I set the image to the default image if it was not loaded but it didn't work

class HomePageTVC: UITableViewCell {

    @IBOutlet weak var stream_image: UIImageView!

    var pic_height: Int?




    override func awakeFromNib() {
        super.awakeFromNib()
      stream_image.image = #imageLiteral(resourceName: "defaultImage")


    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

      

any suggestions would be great

+3


source to share


1 answer


You are facing a fairly common problem of reusing cells. When you delete a cell that was previously used, it may already have an image set in its image view. Before starting the asynchronous download, set the image to zero:

  if let imageString = stream_image_string[indexPath.row].characters,
      !imageString.isEmpty {
    if let image = Stream_Cache.object(forKey: imageString) as? UIImage {
      cell.stream_image.image = image
    } else {
      //Clear out any old image left in the recycled image view.
      cell.stream_image.image = nil
      //Your code to download the image goes here
    }
  }

      



Note that there is no need to wrap code cell.stream_image.image = image

when called DispatchQueue.main.async()

. This code will run on the main thread.

You need to do a second wrapper DispatchQueue.main.async()

around the code inside the input completion file, since the URLSession

default completion handlers are called in the background by default.

+4


source







All Articles