ios – Threading Subject in UICollectionViewCell having Photographs
[ad_1]
I’ve a UICollectionViewCell
subclass which accommodates easy UIImageView
subclass and UILabel
subclass.
My subject is when collectioView
is scrolled quick the cells are exhibiting completely different photographs than the one which they’re supposed to indicate. I do know it’s because the cells are reused and when new cells are proven they’re principally the previous cells which went out of view coz of scrolling. And completely different photographs are proven trigger every cell could fetches a number of photographs from the a number of urls coz of reusing .
repair this threading subject?
Issues I’ve tried,
- I’ve
lastDownloadedImageUrl
which preserve monitor of final url {that a} cell used to fetch the picture and whereas setting the picture toimageView
in cell I examine whether or not the url String is identicallastDownloadedImageUr
if not then I will not set the picture.
My mannequin for cell encompass array of struct referred to as ListModel
which has identify
and imgUrl
struct ListModel : Hashable{
let identify : 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: .heart, 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.identify
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 photographs in my CLImageView
utilizing the beneath code and pictures are cached contained in the RequestManager
func downloadImageFrom(urlStr: String) {
Process{
do{
let information = attempt await requestManager.downloadImage(from: urlStr)
guard let downloadedImage = UIImage(information: information) else {
DispatchQueue.fundamental.async {
self.activityIndicator.stopAnimating()
self.picture = self.placeHolderImage
self.contentMode = .scaleAspectFit
}
return
}
DispatchQueue.fundamental.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’d respect any assist .
[ad_2]