ios – Threading Challenge in UICollectionViewCell having Pictures

[ad_1]

I’ve a UICollectionViewCell subclass which incorporates easy UIImageView subclass and UILabel subclass.

My subject is when collectioView is scrolled quick the cells are exhibiting completely different photos than the one which they’re supposed to point out. I do know it’s because the cells are reused and when new cells are proven they’re mainly the outdated cells which went out of view coz of scrolling. And completely different photos are proven trigger every cell might fetches a number of photos from the a number of urls coz of reusing .

repair this threading subject?

Issues I’ve tried,

  1. I’ve lastDownloadedImageUrl which maintain observe of final url {that a} cell used to fetch the picture and whereas setting the picture to imageView in cell I verify whether or not the url String is identical lastDownloadedImageUr if not then I will not set the picture.

My mannequin for cell encompass array of struct known as ListModel which has title and imgUrl

struct ListModel : Hashable{
    let title : String
    let imgUrl : String?
}

In my ViewController I’ve assortment view added as subview and I am utilizing UICollectionViewDiffableDataSource. Right here is my code for assortment view cell configuration

    personal func configureDataSource(){
    guard let collectionView = collectionView else {return}
    dataSource = UICollectionViewDiffableDataSource<Part,ListModel>(collectionView: collectionView, cellProvider: { collectionView, indexPath, listModel in
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CLCatBreedListCell.reuseId, for: indexPath) as! CLCatBreedListCell
        cell.set(mannequin: listModel)
        return cell
    })
}

My CLCatBreedListCell ,

protocol ImageDownloadingProtocol : AnyObject {
    func shouldSetDownloadedImage(forUrl urlStr: String) -> Bool
}

class CLCatBreedListCell : UICollectionViewCell{
    
    static let reuseId = "CatbreedListCell"
    
    let catImageView : CLImageView = ViewFactory.getCLImageView()
    let catBreedNameLabel = CLTitleLabel(txtAlignment: .middle, fontSize: 14)
    
    var lastDownloadedImageUrl : String = ""
    
    override init(body: CGRect) {
        tremendous.init(body: body)
        configure()
    }
    
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been applied")
    }
    
    
    personal func configure(){
        addSubview(catImageView)
        addSubview(catBreedNameLabel)
        catImageView.delegate = self
        
        let padding: CGFloat = 5
        
        NSLayoutConstraint.activate([
            catImageView.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor,constant: padding),
            catImageView.trailingAnchor.constraint(lessThanOrEqualTo: trailingAnchor,constant: -padding),
            catImageView.topAnchor.constraint(equalTo: topAnchor,constant: padding),
            catImageView.heightAnchor.constraint(equalToConstant: 100),
            catImageView.widthAnchor.constraint(equalToConstant: 100),
            
            catBreedNameLabel.topAnchor.constraint(equalTo: catImageView.bottomAnchor, constant: padding),
            catBreedNameLabel.leadingAnchor.constraint(equalTo: leadingAnchor,constant: padding),
            catBreedNameLabel.trailingAnchor.constraint(equalTo: trailingAnchor,constant: -padding),
            catBreedNameLabel.heightAnchor.constraint(equalToConstant: 20)
        ])
    }
    
    
    func set(mannequin : ListModel){
        catBreedNameLabel.textual content = mannequin.title
        lastDownloadedImageUrl = mannequin.imgUrl ?? ""
        if let imgURL = mannequin.imgUrl {
            catImageView.downloadImageFrom(urlStr: imgURL)
        }else {            
            catImageView.configureForFailedImageDowload()
        }
    }
}


extension CLCatBreedListCell : ImageDownloadingProtocol{
    
    func shouldSetDownloadedImage(forUrl urlStr: String) -> Bool {
        if lastDownloadedImageUrl == urlStr{
            return true
        }else {
            return false
        }
    }
}

I obtain photos in my CLImageView utilizing the under code and pictures are cached contained in the RequestManager

 func downloadImageFrom(urlStr: String) {
    Process{
        do{
            let knowledge = attempt await requestManager.downloadImage(from: urlStr)
            guard let downloadedImage = UIImage(knowledge: knowledge) else {
                DispatchQueue.essential.async {
                    self.activityIndicator.stopAnimating()
                    self.picture = self.placeHolderImage
                    self.contentMode = .scaleAspectFit
                }
                return
            }
            
            DispatchQueue.essential.async {
                guard let delegate = self.delegate else {return}
                if delegate.shouldSetDownloadedImage(forUrl: urlStr) {
                    self.configure(catImage: downloadedImage)
                    
                    self.activityIndicator.stopAnimating()
                    self.picture = downloadedImage
                    self.contentMode = .scaleToFill
                }
            }
        }catch{
            self.configureForFailedImageDowload()
        }
    }
}

I might respect any assist .

[ad_2]

Leave a Reply