如何从UICollectionView使用NSCache一个web服务器异步加载图片如何从UICol

2019-05-12 13:55发布

我有一些问题,在使用UICollectionView一个NScache web服务器加载图像时。

问题:

该图像不适合显示:

  1. 有时它们不是在对应的小区showned

要么

  1. 图像被改变上滚动

情况:

  1. 我有3个阵列whitch被正确地从web服务器加载功能viewDidLoad中()。 这些阵列是:vPrice,vTitle和vImages_api

  2. 我对细胞的自定义类有:

    • 标签价格:cell.lblPrice

    • 标签标题:cell.lblTitle

    • 图片:cell.imgPicture

我相信这个问题是在函数func的CollectionView(_的CollectionView:UICollectionView,cellForItemAt indexPath:IndexPath) - > UICollectionViewCell

这可能与要么我用NSCache的方式,或者我用的方式,当我使用DispatchQueue。

代码:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = self.collectionViewPRODUSE.dequeueReusableCell(withReuseIdentifier: "customCell", for: indexPath) as! clsCustomCell

    cell.lblPrice.text = vPrice[indexPath.item]
    cell.lblTitle.text = vTitle[indexPath.item]

    cell.layer.borderColor = UIColor.lightGray.cgColor
    cell.layer.borderWidth = 0.5

    DispatchQueue.global(qos: .userInitiated).async {
        //background thread
        let ImageString = self.vImages_api[indexPath.item]
        let imageUrl = URL(string: ImageString)
        let imageData = NSData(contentsOf: imageUrl!)

        // main thread to update the UI
        DispatchQueue.main.async {
            let key1 = self.vImages_api[indexPath.item] as AnyObject
            //if i saved allready my image in cache, then i will load my image from cache
            if let imageFromCache = self.objCache.object(forKey: key1){
                cell.imgPicture.image = imageFromCache as! UIImage
            }
            else{//if my image is not in cache  ......
                        if imageData != nil {
                            let myPicture = UIImage(data: imageData! as Data)
                            cell.imgPicture.image = myPicture                 

                            //save my image in cache
                            self.objCache.setObject(myPicture!, forKey: ImageString as AnyObject)
                        }
            }
        }
    }

    return cell
}

编辑代码- II版本:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = self.collectionViewPRODUSE.dequeueReusableCell(withReuseIdentifier: "MyCustomCell", for: indexPath) as! clsCustomCell

    cell.lblPret.text = vPrice[indexPath.item]
    cell.lblTitlu.text = vTitle[indexPath.item]

    cell.layer.borderColor = UIColor.lightGray.cgColor
    cell.layer.borderWidth = 0.5
    let key1 = self.vImages_api[indexPath.item] as AnyObject

    if let imageFromCache = self.objCache.object(forKey: key1){
        cell.imgPicture.image = imageFromCache as! UIImage
    }else{
        DispatchQueue.global(qos: .background).async {
            let ImageString = self.vImages_api[indexPath.item]
            let imageUrl = URL(string: ImageString)
            let imageData = NSData(contentsOf: imageUrl!)
            let  myPicture = UIImage(data: imageData! as Data)
            self.objCache.setObject(poza!, forKey: ImageString as AnyObject)
                DispatchQueue.main.async {
                    if imageData != nil {
                        cell.imgPicture.image = myPicture
                    }
                }
        }

    }

    return cell
}

编辑代码- III版

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = self.collectionViewPRODUSE.dequeueReusableCell(withReuseIdentifier: "celula_custom", for: indexPath) as! clsCustomCell
    cell.lblPret.text = vPrice[indexPath.item]
    cell.lblTitlu.text = vTitle[indexPath.item]

  NKPlaceholderImage(image: UIImage(named: "loading"), imageView: cell.imgPicture, imgUrl:  self.vImages_api[indexPath.item]
    ) { (image11) in
        cell.imgPicture.image = image11
    }
    cell.layer.borderColor = UIColor.lightGray.cgColor
    cell.layer.borderWidth = 0.5

    return cell
}

Answer 1:

试试这个它的工作代码(SWIFT 4)。

func NKPlaceholderImage(image:UIImage?, imageView:UIImageView?,imgUrl:String,compate:@escaping (UIImage?) -> Void){

    if image != nil && imageView != nil {
        imageView!.image = image!
    }

    var urlcatch = imgUrl.replacingOccurrences(of: "/", with: "#")
    let documentpath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
    urlcatch = documentpath + "/" + "\(urlcatch)"

    let image = UIImage(contentsOfFile:urlcatch)
    if image != nil && imageView != nil
    {
        imageView!.image = image!
        compate(image)

    }else{

        if let url = URL(string: imgUrl){

            DispatchQueue.global(qos: .background).async {
                () -> Void in
                let imgdata = NSData(contentsOf: url)
                DispatchQueue.main.async {
                    () -> Void in
                    imgdata?.write(toFile: urlcatch, atomically: true)
                    let image = UIImage(contentsOfFile:urlcatch)
                    compate(image)
                    if image != nil  {
                        if imageView != nil  {
                            imageView!.image = image!
                        }
                    }
                }
            }
        }
    }
}

使用这样:

// Here imgPicture = your imageView and UIImage(named: "placeholder") is Display image brfore download actual image.  
imgPicture.image = nil 
NKPlaceholderImage(image: UIImage(named: "placeholder"), imageView: imgPicture, imgUrl: "Put Here your server image Url Sting") { (image) in }


文章来源: How to asynchronous load image from a web-server in UICollectionView using NSCache