Gianfranco Lemmo Gianfranco Lemmo - 4 months ago 47
iOS Question

UICollectionView Load image in the wrong position while scrolling Alamofire

The problem is When is load the Application for the first time, for the delay of connection the images load in the wrong position when the scroll the collection the images will change a few times until the scroll will end and the image will go back to the right image. I have no idea why this is happening. After the application is loaded the images take the correct position. I use Alamofire and Alamofire Image.

Model Noticia:

import UIKit
import SwiftyJSON
import Alamofire
import AlamofireImage

class Noticia: NSObject {
//MARK: - Properties
var name:String = ""
var image:String = ""
var number:Int = 0
let photoCache = AutoPurgingImageCache(
memoryCapacity: 100 * 1024 * 1024,
preferredMemoryUsageAfterPurge: 60 * 1024 * 1024
)

override init() {

}

func setData(obj:JSON)->Noticia{
self.name = obj["titulo"].stringValue
self.image = obj["imagen_portada"].stringValue
self.number = Int(obj["id"].stringValue)!
return self
}

//MARK: - Image Caching

func cacheImage(image: Image, urlString: String) {
photoCache.addImage(image, withIdentifier: urlString)
}

func cachedImage(urlString: String) -> Image? {
return photoCache.imageWithIdentifier(urlString)
}

}


ViewController

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! NoticiaCell
let cell2 = collectionView.dequeueReusableCellWithReuseIdentifier("CellBillboard", forIndexPath: indexPath) as! BillboardCell
//Billboard Cell
if(indexPath.item == 0){
cell2.contact = noticia[indexPath.item]
return cell2
}else{
//Square News Cell
cell.contact = noticia[indexPath.item]
cell.layer.borderColor = ConstantProjectClass.colorBorderWebBizarro.CGColor
cell.layer.borderWidth = ConstantProjectClass.noticiasBorderWidth
//Layout custom
cell.setNeedsLayout()
cell.layoutIfNeeded()
return cell
}

}


Noticia Cell

import UIKit
import Alamofire
import AlamofireImage

class NoticiaCell: UICollectionViewCell {
//MARK: - Properties
@IBOutlet weak var labelView: UILabel!
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var topLabelConstraint: NSLayoutConstraint!
@IBOutlet weak var topImageConstraint: NSLayoutConstraint!
var imageUrlString:String?

var contact:Noticia = Noticia(){
didSet{
self.labelView.text = self.contact.name

imageUrlString = self.contact.image

self.imageView.image = nil

if let imageFromCache = self.contact.cachedImage(imageUrlString!){
self.imageView.image = imageFromCache
return
}

Alamofire.request(.GET, self.contact.image)
.responseImage { response in
if let image = response.result.value {
dispatch_async(dispatch_get_main_queue(), {
let imageToCache = image
self.imageView.image = imageToCache
self.contact.cacheImage(imageToCache, urlString: self.contact.image)
})
}
}
}
}
}


Any Help?

Answer

After read several post I founded the solution:

ViewController

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! NoticiaCell
        let cell2 = collectionView.dequeueReusableCellWithReuseIdentifier("CellBillboard", forIndexPath: indexPath) as! BillboardCell
        print("entro")
        //Billboard Cell
        if(indexPath.item == 0){
            cell2.contact = noticia[indexPath.item]
            return cell2
        }else{
            //Square News Cell
            cell.labelView.text = noticia[indexPath.item].name

            imageUrlString = noticia[indexPath.item].image

            cell.imageView.image = nil

            if let imageFromCache = noticia[indexPath.item].cachedImage(imageUrlString!){
                cell.imageView.image = imageFromCache

            }else{

                Alamofire.request(.GET, noticia[indexPath.item].image)
                    .responseImage { response in
                        if let image = response.result.value {
                            let imageToCache = image

                            if let updatedCell = collectionView.cellForItemAtIndexPath(indexPath) as? NoticiaCell{
                                updatedCell.imageView.image = imageToCache
                            }

                            self.noticia[indexPath.item].cacheImage(imageToCache, urlString: self.noticia[indexPath.item].image)

                        }
                }
            }

            cell.layer.borderColor = ConstantProjectClass.colorBorderWebBizarro.CGColor
            cell.layer.borderWidth = ConstantProjectClass.noticiasBorderWidth
            //Layout custom
            cell.setNeedsLayout()
            cell.layoutIfNeeded()
            return cell

        }
    }

The key is the following code:

if let updatedCell = collectionView.cellForItemAtIndexPath(indexPath) as? NoticiaCell{
    updatedCell.imageView.image = imageToCache
}