使用版本Xcode 6.3, Swift 1.2
从名字上可以感觉出来,Cache,缓存。我们都知道,有时候一些计算量比较大的结果,我们可以缓存起来,下次使用时,可以直接使用,不用重复计算。
简单的例子来说吧。例如我们有一些图片需要使用,这些图片资源是从网络上获取来的。我们直观上的感觉就是不用每次使用图片都从网络上去获取,可以将得到的图片缓存起来,需要使用的时候,我们可以直接拿来用。
如果没有NSCache,你会怎么做,我的第一反应是 ------> Dictionary,字典。
字典的实现
字典,有 ** key--value 键-值对**,所以通过url(String)--image这样的组合,我们可以实现一个简单的缓存。例如:
var imageCache = Dictionary < String,UIImage >() let url = "图片的URL" let image = imageCache[url] if image == nil { // 如果imageCache中没有该url对应的图片,则访问url,获取图片,放在imageCache中 let request = NSURLRequest(URL : NSURL(string : url!)!) let session = NSURLSession.sharedSession() let task = session.dataTaskWithRequest(request){ (data,response,error) -> Void in if(error == nil){ let image = UIImage(data: data) //放入imageCache中 self.imageCache[url!] = image //可以使用图片 } } task.resume() }else{ // 如果imageCache中已经有了图片,则可以直接使用。 }
使用NSCache
上面的实现,似乎已经可以满足要求了,可是,有一个问题,如果图片资源过多,程序运行时占据太多存储资源。我们希望,如果图片长时间不用的话,可以释放它,等需要用时,在从网络中获取。在时间和空间中,取一个权衡。
那么好了,NSCache可以帮我们做到这一点。它就像一个容器一样,内部存储的也是key-value 对,它类似Dictionary,但不同的是,当空间比较紧张的时候,NSCache可以释放一部分资源。正因为需要释放资源,NSCache存储的对象需要实现 NSDiscardableContent 协议。
可以参照ios developer library NSCache,来看看它的使用方式。
下面看一个,取代上面图片缓存的例子:
import UIKit class ImageLoader { var cache = NSCache() class var sharedLoader : ImageLoader { struct Static { static let instance : ImageLoader = ImageLoader() } return Static.instance } func imageForUrl(urlString: String,completionHandler:(image: UIImage?,url: String) -> ()) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0),{()in var data: NSData? = self.cache.objectForKey(urlString) as? NSData if let goodData = data { let image = UIImage(data: goodData) dispatch_async(dispatch_get_main_queue(),{() in completionHandler(image: image,url: urlString) }) return } var downloadTask: NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: urlString)!,completionHandler: {(data: NSData!,response: NSURLResponse!,error: NSError!) -> Void in if (error != nil) { completionHandler(image: nil,url: urlString) return } if data != nil { let image = UIImage(data: data) self.cache.setObject(data,forKey: urlString) dispatch_async(dispatch_get_main_queue(),{() in completionHandler(image: image,url: urlString) }) return } }) downloadTask.resume() }) } }
使用:
ImageLoader.sharedLoader.imageForUrl("图片的URL",completionHandler:{(image: UIImage?,url: String) in //这里写你的completionHandler })
笔者注:欢迎非商业转载,但请一定注明出处
如果你认为这篇不错,也有闲钱,那你可以用支付宝随便捐助一点,以慰劳笔者的辛苦: