How can flickering of images be eliminated when scrolling table cells?
sobes.tech AI
Answer from AI
The flickering of images when scrolling UITableView or UICollectionView can be mitigated by the following methods:
-
Image caching: Use
NSCacheorURLCacheto store loaded images by URL. Check the cache before requesting an image.import UIKit let imageCache = NSCache<NSURL, UIImage>() func loadImage(from url: URL, completion: @escaping (UIImage?) -> Void) { // Check cache before loading if let cachedImage = imageCache.object(forKey: url as NSURL) { completion(cachedImage) return } // Load image asynchronously URLSession.shared.dataTask(with: url) { data, response, error in guard let data = data, error == nil else { completion(nil) return } if let loadedImage = UIImage(data: data) { // Cache the loaded image imageCache.setObject(loadedImage, forKey: url as NSURL) completion(loadedImage) } else { completion(nil) } }.resume() } -
Asynchronous loading: Load images in a background thread to avoid blocking the main UI thread. Use
URLSessionor third-party libraries (e.g., Kingfisher, SDWebImage, Nuke).import UIKit func configureImageView(_ imageView: UIImageView, with url: URL) { imageView.image = nil // Clear image before loading // Example with URLSession (can use third-party libraries) loadImage(from: url) { loadedImage in // Update UI on main thread DispatchQueue.main.async { imageView.image = loadedImage } } } -
Placeholder image: Show a temporary placeholder image until the main image is fully loaded.
// In cellForRowAt / cellForItemAt cell.imageView.image = UIImage(named: "placeholder") // Set placeholder // When image is loaded DispatchQueue.main.async { cell.imageView.image = loadedImage // Set loaded image } -
Cancel loading when reusing cells: Cancel the current image load in
prepareForReuse()if it is still ongoing. This prevents setting the wrong image in the cell.class CustomCell: UITableViewCell { let customImageView = UIImageView() private var dataTask: URLSessionDataTask? override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) // Setup customImageView } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func configure(with url: URL) { customImageView.image = UIImage(named: "placeholder") dataTask?.cancel() // Cancel previous load dataTask = URLSession.shared.dataTask(with: url) { data, response, error in guard let data = data, error == nil else { return } if let loadedImage = UIImage(data: data) { DispatchQueue.main.async { self.customImageView.image = loadedImage } } } dataTask?.resume() } override func prepareForReuse() { super.prepareForReuse() customImageView.image = nil // Clear or set placeholder dataTask?.cancel() // Cancel load on reuse } } -
Using
Kingfisher,SDWebImage, orNuke: These libraries provide ready-made solutions for caching, asynchronous loading, and canceling loads, greatly simplifying image handling.import Kingfisher // Example with Kingfisher let url = URL(string: imageName)! imageView.kf.indicatorType = .activity // Show loading indicator imageView.kf.setImage( with: url, placeholder: UIImage(named: "placeholder"), options: [ .transition(.fade(1)) // Fade animation when setting image ])
When these techniques are properly applied, flickering during scrolling will be minimized.