UICollectionView 在滚动 Alamofire 时将图像加载到错误的位置

Posted

技术标签:

【中文标题】UICollectionView 在滚动 Alamofire 时将图像加载到错误的位置【英文标题】:UICollectionView Load image in the wrong position while scrolling Alamofire 【发布时间】:2016-07-23 02:18:13 【问题描述】:

问题是第一次加载应用程序时,由于连接延迟,当滚动集合时,图像加载到错误的位置,图像会改变几次,直到滚动结束,图像就会消失回到正确的图像。我不知道为什么会这样。加载应用程序后,图像将位于正确的位置。我使用 Alamofire 和 Alamofire Image。

模型公告:

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)
    


视图控制器

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
    


通知单元

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)
                        )
                    
                
            
    

有什么帮助吗?

【问题讨论】:

我建议在集合视图中避开尾随和底部约束。使用具有出口的宽度约束的前导和顶部约束。动态设置宽度并给出纵横比,或者寻找另一条路线。 Example 【参考方案1】:

看了几篇帖子,我找到了解决办法:

视图控制器

    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

        
    

关键是以下代码:

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

【讨论】:

以上是关于UICollectionView 在滚动 Alamofire 时将图像加载到错误的位置的主要内容,如果未能解决你的问题,请参考以下文章

创建一个与另一个 UICollectionView 一起滚动的 UICollectionView

UICollectionView 在滚动时响应?

向上滚动时保持 UICollectionView 中的滚动位置

UITableView中的多个UICollectionView在滚动中交织在一起

在 UICollectionView 中滚动时绕过 UIScrollViewDelegate

在 UICollectionViewCell 内的 UICollectionView 中平滑滚动