在Swift中的collectionViewCell中缓存图像?

时间:2015-09-15 03:26:46

标签: ios swift caching parse-platform uicollectionviewcell

我的collectionViewCell中的图像是通过NSURLRequest获取和解析的,我如何缓存这些图像,以便他们不必在视图的每次出现/消失时都开始新的请求?

这是我的代码,用于获取图像:

class funnyPicture: NSObject {

    var pfPicture : PFObject
    var coverImage : UIImage!

    init(pfPicture: PFObject) {
        self.pfPicture = pfPicture
    }

    func fetchCoverImage(completion: (image: UIImage?, error: NSError?) -> Void) {
        let urlString = self.pfPicture["funnyPictures"] as! String
        let url = NSURL(string: urlString)
        let request = NSURLRequest(URL: url!)
        let queue = dispatch_get_main_queue()

        NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) { (response: NSURLResponse?, data: NSData?, error: NSError?) in
            if error == nil {
                self.coverImage = UIImage(data: data!)
                completion(image: self.coverImage, error: nil)
            } else {
                completion(image: nil, error: error)
            }
        }
    }
}

这是我的collectionView代码,用于将图像解析为collectionViewCell:

   override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! MyCollectionViewCell

        // Configure the cell
        let book = self.books[indexPath.row]
        let coverImage = book.coverImage
        if coverImage == nil {
            book.fetchCoverImage({ (image, error) -> Void in
                if self.collectionView != nil {
                    collectionView.reloadItemsAtIndexPaths([indexPath])
                }
            })
        } else {
            dispatch_async(dispatch_get_main_queue()){
                let imageView = cell.imageView
                imageView.image = book.coverImage
            }
        };
        if book.coverImage == nil {
            cell.imageView.userInteractionEnabled = false
            cell.userInteractionEnabled = false
        }else {
            cell.imageView.userInteractionEnabled = true
            cell.userInteractionEnabled = true

        }

        return cell
    }

虽然我已经收到了对第三方框架的引用,但我还没有收到任何关于如何使用我在问题中提供的代码实现它们的答案,或者甚至使用已经实现缓存机制的苹果的答案..我把问题放在问题中的原因是在答案中使用..谢谢。

6 个答案:

答案 0 :(得分:4)

以下是集合视图单元格的示例:

import UIKit

let imageCache = NSCache<AnyObject, AnyObject>.sharedInstance

class myCell: UICollectionViewCell {

    @IBOutlet public weak var myImageView: UIImageView?

    private var imageUrlString: String?

    private var downloadTask: URLSessionDownloadTask?
    public var imageURL: URL? {
        didSet {
            self.downloadItemImageForSearchResult(imageURL: imageURL)
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()

        // Initialization code
    }

    public func downloadItemImageForSearchResult(imageURL: URL?) {

        if let urlOfImage = imageURL {
            if let cachedImage = imageCache.object(forKey: urlOfImage.absoluteString as NSString){
            self.myImageView!.image = cachedImage as? UIImage
        } else {
            let session = URLSession.shared
            self.downloadTask = session.downloadTask(
                with: urlOfImage as URL, completionHandler: { [weak self] url, response, error in
                    if error == nil, let url = url, let data = NSData(contentsOf: url), let image = UIImage(data: data as Data) {

                        DispatchQueue.main.async() {

                            let imageToCache = image

                            if let strongSelf = self, let imageView = strongSelf.myImageView {

                                imageView.image = imageToCache

                                imageCache.setObject(imageToCache, forKey: urlOfImage.absoluteString as NSString , cost: 1)
                            }
                        }
                    } else {
                        //print("ERROR \(error?.localizedDescription)")
                    }
            })
            self.downloadTask!.resume()
        }
      }
    }

    override public func prepareForReuse() {
      self.downloadTask?.cancel()
      myImageView?.image = UIImage(named: "ImagePlaceholder")
    }

    deinit {
      self.downloadTask?.cancel()
      myImageView?.image = nil
    }
}

不要忘记为NSCache进行扩展 像这样:

import Foundation

extension NSCache {
  class var sharedInstance: NSCache<NSString, AnyObject> {
      let cache = NSCache<NSString, AnyObject>()
      return cache
  }
}

答案 1 :(得分:1)

使用NSCache和NSOperationQueue管理图像加载。在https://stackoverflow.com/a/12721899/5271191概述了该技术的好帖子(它的Objective-C,但Swift的技术是相同的。)

答案 2 :(得分:1)

我强烈建议您为UIImageView使用一个干净的原位替换/扩展,它将透明地管理图像的缓存,并避免维护操作队列等不必要的复杂性。

如果在内存缓存中满足您的需求 - 请查看 -

https://github.com/nicklockwood/AsyncImageView

如果你想要持久缓存,那么这个会做 -

https://github.com/rs/SDWebImage

HTH。

答案 3 :(得分:1)

您应该使用专门的框架。我建议使用SDWebImage,它已经过时且不稳定。

看看这两个与iOS平台最新的库:

  • DFImageManager - 用Objective-C编写的高级框架,但具有可空性注释(适用于Swift)。这里的list of things比SDWebImage更好。 披露:由我撰写,意见可能有偏见。
  • Kingfisher - 用Swift编写的轻量级库。与SDWebImage类似,但SDWebImage和DFImageManager的功能要少得多。

答案 4 :(得分:1)

  

我的collectionViewCell中有图像被提取和解析   通过NSURLRequest,我如何缓存这些图像,以便他们不必这样做   每一次出现/消失都会开始一个新的请求   查看?

URL loading system已经提供了缓存。看看the docs for NSURLCache。如果您所需的资源尚未充分缓存,则可能只需调整分配给应用程序的URL缓存的磁盘空间。

您还应该查看随资源返回的标头(缓存控制,过期等),以确保它们不会阻止缓存。 Here's a short tutorial on cache-related headers.

答案 5 :(得分:-1)

我使用swift 2创建了一个库来执行图像请求并对其进行缓存。试一试非常简单。

https://github.com/georgehadly/GHImageCaching

你所能做的就是这样,

request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField:"Content-Type")

如果您要删除所有缓存的图片

viewImg.getCachedImage("geo", URI: NSURL(string: "https://s-media-cache-ak0.pinimg.com/236x/8e/5a/98/8e5a98795dc2c5322cac97343a6cad6d.jpg")!) { (done) -> Void in
        if(done){
            // your extra
        }
    }