如何使用 NSCache 从 UICollectionView 中的 Web 服务器异步加载图像 [英] How to asynchronous load image from a web-server in UICollectionView using NSCache

查看:28
本文介绍了如何使用 NSCache 从 UICollectionView 中的 Web 服务器异步加载图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用 NScache 从 UICollectionView 中的网络服务器加载图像时遇到了一些问题.

I have some issues when loading images from a web-server in UICollectionView using NScache.

问题:

图片显示不正确:

  1. 有时它们不会显示在相应的单元格中

  1. 图像在滚动时发生变化

情况:

  1. 我在函数 viewDidLoad() 中从网络服务器正确加载了 3 个数组.这些数组是:vPrice、vTitle 和 vImages_api

  1. I have 3 arrays whitch are properly loaded from the web-server in function viewDidLoad(). These arrays are: vPrice, vTitle and vImages_api

我的单元格自定义类有:

my custom class for cell have:

  • 价格标签:cell.lblPrice

  • label for price: cell.lblPrice

标题标签:cell.lblTitle

label for title: cell.lblTitle

图片:cell.imgPicture

image: cell.imgPicture

我相信问题出在函数 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell

I belive that the problem is in function func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell

这可能与我使用 NSCache 的方式有关,也可能与我使用的方式和使用 DispatchQueue 的时间有关.

It could be related either to the way I use NSCache or to the way I use and when I use 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
}

推荐答案

试试这个它的工作代码 (Swift 4).

Try this one it's Working code (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 }

这篇关于如何使用 NSCache 从 UICollectionView 中的 Web 服务器异步加载图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆