skip to Main Content

I develop both android(Java) and IOS(swift) applications. I had a problem on the Android side and I solved it.I’m having the same problem on the IOS side but I couldn’t solve it.

I have a tableview in my application and I fill it with data I get from my own server.

However, when I swipe through the list, sometimes the values ​​and images in the list item get mixed up between the list items.

This little code on the Android side solved my problem

@Override
public long getItemId(int position) {
    return position;
}

@Override
public int getItemViewType(int position) {
    return position;
}

I searched for override methods but I couldn’t find an equivalent event that would solve my problem.

enter image description here

The list interface is like this, a simple list.

enter image description here

Maybe there is a problem with uploading the images, I upload it like this

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "mainCell", for: indexPath) as! MainTableCell
        let item = radio_type_list[indexPath.row]
        cell.RadioTitle.text = item.title
        cell.RadioDescription.text = item.desc
        cell.RadioImage.downloadImageFrom(link:item.imageurl, contentMode: UIView.ContentMode.scaleToFill)
        return cell;
    }

let imageCache = NSCache<NSString, AnyObject>()
extension UIImageView {
    func downloadImageFrom(link:String, contentMode: UIView.ContentMode) {
        let imageCache = NSCache<NSString, AnyObject>()
        if let cachedImage = imageCache.object(forKey: (link as AnyObject) as! NSString) {
                    self.image = cachedImage as? UIImage
                    self.contentMode = .scaleAspectFill
                    return
                }
        
        URLSession.shared.dataTask( with: NSURL(string:link)! as URL, completionHandler: {
            (data, response, error) -> Void in
            DispatchQueue.main.async {
                self.contentMode =  contentMode
                if let data = data { self.image = UIImage(data: data) }
            }
        }).resume()
    }
}

2

Answers


  1. The issue you’re experiencing occurs because the images get mixed up or swapped between cells as they scroll in and out of view

    let imageCache = NSCache<NSString, UIImage>() 
    
    extension UIImageView {
        func downloadImageFrom(link: String, contentMode: UIView.ContentMode) {
            self.contentMode = contentMode
            self.image = nil // Clear the image initially to prevent reuse issues
    
           
            if let cachedImage = imageCache.object(forKey: link as NSString) {
                self.image = cachedImage
                return
            }
            
     
            URLSession.shared.dataTask(with: URL(string: link)!) { data, response, error in
                guard let data = data, error == nil, let downloadedImage = UIImage(data: data) else {
                    return
                }
    
                // Cache the downloaded image
                imageCache.setObject(downloadedImage, forKey: link as NSString)
                
                
                DispatchQueue.main.async {
                    self.image = downloadedImage
                }
            }.resume()
        }
    }
    
    Login or Signup to reply.
  2. You can learn more about dequeue mechanisim of ios following this link

    So when you scroll through your list, whenever a cell get dequeue, you start a download image task from an UIImageView. The problem arise when cell got reuse, there is a chance the old download task take longer time than the new download task one for that cell. Here is my suggestion code to fix your problem:

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "mainCell", for: indexPath) as! MainTableCell
        let item = radio_type_list[indexPath.row]
        cell.RadioTitle.text = item.title
        cell.RadioDescription.text = item.desc
        cell.bind(imageUrl: item.imageurl, contentMode: UIView.ContentMode.scaleToFill)
        return cell;
    }
    
    class MainTableCell: UITableViewCell {
        var RadioImage = UIImageView()
        
        var imageUrl: String = ""
        
        override func prepareForReuse() {
            super.prepareForReuse()
            RadioImage.image = nil // remove old image
        }
        
        func bind(imageUrl: String, contentMode: UIView.ContentMode) {
            self.imageUrl = imageUrl
            RadioImage.downloadImageFrom(link: imageUrl, contentMode: contentMode) { [weak self] _image, contentMode, imageUrl in
                guard let self = self,
                      self.imageUrl == imageUrl // <- compare to current imageUrl of cell to display image correctly
                else { return }
                self.RadioImage.image = _image
                self.RadioImage.contentMode = contentMode
            }
        }
    }
    
    let imageCache = NSCache<NSString, UIImage>()
    extension UIImageView {
        func downloadImageFrom(link:String, contentMode: UIView.ContentMode, completion: ((UIImage, UIView.ContentMode, String) -> Void)?) {
            if let cachedImage = imageCache.object(forKey: (link as AnyObject) as! NSString) {
                completion?(cachedImage, .scaleAspectFill, link)
                        return
                    }
            
            URLSession.shared.dataTask( with: NSURL(string:link)! as URL, completionHandler: {
                (data, response, error) -> Void in
                DispatchQueue.main.async {
                    if let data = data,
                       let image = UIImage(data: data)
                    {
                        imageCache.setObject(image, forKey: link as NSString)
                        completion?(image, contentMode, link)
                    }
                }
            }).resume()
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search