开发时,经常会遇到一个问题,从网络下载的图片应该如何来缓存?难道每次请求都要去下载一次?流量不要钱哇?所以比较好的方法就是把图片资源下载下来,保存到本地,然后下次直接从本地取出图片就可以了,但是用什么来保存这个图片呢?有些人可能说用NSDictionary(应该是NSMutableDictionary),因为这个类在开发中非常非常常用。但是其实可能有一个更好的选择,是专门为缓存来设计的,没错,就是NSCache。非常牛逼的AFN、SDWebImage都是用它来进行图片缓存的。
就像上边说到的,NSCache和NSDictionary很类似,用key-value键值对来存储,但是相对于NSDictionary,他有几点优势:
- 1.NSCache结合了各种自动删除的策略,用来确保不会占用过多的系统内存。
- 2.NSCache是线程安全的,在多线程情况下,不需要考虑加锁来保证数据的安全。
- 3.不像NSMutableDictionary,NSCache不会copy对象,而是保留它。
NSCache 框架
NSCache的类中内容很少,从Xcode进去看也就只有43行,接下来我们来看一下他都提供了哪些方法和属性。
NSCache 的属性
1 |
@property NSUInteger countLimit;
|
countLimit
用来限制缓存最多维护的对象个数,默认为0,0表示不限制数量。
但是需要注意的是,这个限制并不是严格的限制,如果缓存的数量超过这个数量,缓存中的一个对象可能会被立即丢弃,也可能稍候丢弃,还可能永远都不会丢弃,具体还要看实现的方式。
1 |
@property NSUInteger totalCostLimit;
|
totalCostLimit
用来限制缓存最大能够维持的内存,默认也为0,表示没有限制。
一般我们会使用字节来作为cost进行限制,在添加缓存时可以指定写入的缓存的cost,当总消耗的cost值超过限制时,就会释放一些缓存对象,这个释放对象的选择使用LRU(Least Recently Used)算法来选择最近没有使用的对象进行淘汰。
NSCache 方法
NSCache的存取方法主要是用key-value的形式,存取方法分为set、get、remove三种类型。
1 2 3 4 5 6 |
- (nullable ObjectType)objectForKey: (KeyType)key; - (void)setObject: (ObjectType)obj forKey: (KeyType)key; // 0 cost - (void)setObject: (ObjectType)obj forKey: (KeyType)key cost: (NSUInteger)g; - (void)removeObjectForKey: (KeyType)key; - (void)removeAllObjects; |
其中
1 |
- (void)setObject: (ObjectType)obj forKey: (KeyType)key cost: (NSUInteger)g; |
可以指定消耗的cost,配合之前的totalCostLimit
来管理缓存大小。
NSCacheDelegate
NSCacheDelegate只有一个方法:
1 |
- (void) cache:(NSCache *) cache willEvictObject:( id)obj; |
当代理对象即将从缓存中移除时激活。
NSCache 使用
NSCache的使用很简单。
实例化一个cache对象,然后设定缓存内容就可以了,但是我们
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
self.myCache = [[ NSCache alloc] init]; self.myCache.delegate = self; //设置最大缓存数量:10 self.myCache.countLimit = 10; //设置最大缓存cost:5M self.myCache.totalCostLimit = 5 * 1024 * 1024; for( NSInteger i = 0 ; i < 100 ; i ) { UIImage *image = [ UIImage imageNamed: @"111.jpg"]; NSData *data = UIImageJPEGRepresentation(image, 1.0); NSString *keyStr = [ NSString stringWithFormat: @"image%ld",i]; [ self.myCache setObject:data forKey:keyStr]; } |
然后添加一个按钮,在点击时获取缓存
1 2 3 4 5 6 7 8 9 10 11 12 13 |
- ( IBAction)getBtnClicked:( id)sender { for( NSInteger i = 0 ; i < 100 ; i ) { NSString *keyStr = [ NSString stringWithFormat: @"image%ld",i]; NSData *data = [ self.myCache objectForKey:keyStr]; NSLog( @"%ld",[data length]); } } |
可以看到打印出来的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
... 2018-04-08 17: 41: 16.916639 0800 CacheDemo[ 56627: 2584885] 0 2018-04-08 17: 41: 16.916978 0800 CacheDemo[ 56627: 2584885] 0 2018-04-08 17: 41:16.917196 0800 CacheDemo[ 56627: 2584885] 0 2018-04-08 17: 41: 16.917504 0800 CacheDemo[ 56627: 2584885] 0 2018-04-08 17: 41: 16.917818 0800 CacheDemo[ 56627: 2584885] 0 2018-04-08 17: 41: 16.918076 0800 CacheDemo[ 56627: 2584885] 0 2018-04-08 17: 41: 16.918456 0800 CacheDemo[ 56627: 2584885] 0 2018-04-08 17: 41: 16.918640 0800 CacheDemo[ 56627: 2584885] 0 2018-04-08 17: 41: 16.918945 0800 CacheDemo[ 56627: 2584885] 0 2018-04-08 17: 41:16.919214 0800 CacheDemo[ 56627: 2584885] 0 2018-04-08 17: 41: 16.919521 0800 CacheDemo[ 56627: 2584885] 0 2018-04-08 17: 41: 16.919740 0800 CacheDemo[ 56627: 2584885] 0 2018-04-08 17: 41: 16.920067 0800 CacheDemo[ 56627: 2584885] 0 2018-04-08 17: 41: 16.920571 0800 CacheDemo[ 56627: 2584885] 0 2018-04-08 17: 41: 16.920829 0800 CacheDemo[ 56627: 2584885] 0 2018-04-08 17: 41: 16.921340 0800 CacheDemo[ 56627: 2584885] 0 2018-04-08 17: 41: 16.921631 0800 CacheDemo[ 56627: 2584885] 0 2018-04-08 17: 41: 16.921903 0800 CacheDemo[ 56627: 2584885] 9132462 2018-04-08 17: 41:16.922146 大专栏 iOS开发-NSCache0800 CacheDemo[ 56627: 2584885] 9132462 2018-04-08 17: 41: 16.922386 0800 CacheDemo[ 56627: 2584885] 9132462 2018-04-08 17: 41: 16.922575 0800 CacheDemo[ 56627: 2584885] 9132462 2018-04-08 17: 41: 16.922783 0800 CacheDemo[ 56627: 2584885] 9132462 2018-04-08 17: 41: 16.923082 0800 CacheDemo[ 56627: 2584885] 9132462 2018-04-08 17: 41: 16.923476 0800 CacheDemo[ 56627: 2584885] 9132462 2018-04-08 17: 41: 16.923756 0800 CacheDemo[ 56627: 2584885] 9132462 2018-04-08 17: 41: 16.923991 0800 CacheDemo[ 56627: 2584885] 9132462 2018-04-08 17: 41: 16.924333 0800 CacheDemo[ 56627: 2584885] 9132462 |
发现还是有10个图片被保存了下来,这时候我们把限制的cost大小和存入cost的方法修改一下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
self.myCache = [[ NSCache alloc] init]; self.myCache.delegate = self; //设置最大缓存数量:10 self.myCache.countLimit = 10; //设置最大缓存cost:10M self.myCache.totalCostLimit = 10 * 1024 * 1024; for( NSInteger i = 0 ; i < 100 ; i ) { UIImage *image = [ UIImage imageNamed: @"111.jpg"]; NSData *data = UIImageJPEGRepresentation(image, 1.0); NSString *keyStr = [ NSString stringWithFormat: @"image%ld",i]; // [self.myCache setObject:data forKey:keyStr]; //存入时添加cost [ self.myCache setObject:data forKey:keyStr cost:[data length]]; } |
打印结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
2018-04-08 17: 43: 36.566623 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.566814 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.567049 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.567326 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.567738 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43:36.568164 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.568451 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.568780 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43:36.569227 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.569489 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.569771 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.569993 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.570265 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.570518 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.570832 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.571092 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.571305 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.571526 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.571921 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.572595 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.572763 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.572979 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.573266 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.573541 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.573775 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.573969 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43:36.574232 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.574565 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43:36.575234 0800 CacheDemo[ 56686: 2587750] 0 2018-04-08 17: 43: 36.575364 0800 CacheDemo[ 56686: 2587750] 9132462 |
发现只有最后一次的图片被缓存下来了。
最后
以上就是NSCache的全部内容了,这个类中的内容不多,但是可能会在开发时帮助我们解决很多麻烦的问题。