使用版本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
})
笔者注:欢迎非商业转载,但请一定注明出处
如果你认为这篇不错,也有闲钱,那你可以用支付宝随便捐助一点,以慰劳笔者的辛苦: