写高质量OC代码52建议总结:50.构建缓存时选用NSCache而非NSDictionary

来源:互联网 发布:microsoft相机软件 编辑:程序博客网 时间:2024/05/20 21:22
NSCache胜过NSDictionary之处在于,当系统资源耗尽时,他可以自动删减缓存,用字典就得自己写挂钩,系统低内存时手工删减,十分复杂。
 NSCache不会“拷贝”键而是“保留”,这个点字典也能实现但是很复杂(49条~)。很多时候键都是由不支持拷贝的对象充当的,这点用起来比字典方便。NSCache是线程安全的,多个线程可以同时访问NSCache。
 可以控制缓存删减的实际,有两个参数可以调整,一个是缓存中的对象总数,第二个是所有对象的总开销。

 向缓存中加入的对象必须可以很快的计算出开销值。如果计算过程复杂会大大浪费资源,违背缓存的设计初衷。如果加入缓存的对象是NSData,直接可以将数据大小作为开销值,不需要计算,已经是NSData的一个属性了。

#import "fiftyDemo.h"typedef void(^EOCNetworkFercherCompletionHandler)(NSData *data);@interface EOCNetworkFetcher : NSObject-(id)initWithURL:(NSURL *)url;-(void)startWithCompletionHandler:(EOCNetworkFercherCompletionHandler)handler;@end@implementation fiftyDemo {    NSCache *_cache;}-(id)init {    self = [super init];    if (self) {        _cache = [NSCache new];                _cache.countLimit = 100;    //  最大对象数100                _cache.totalCostLimit = 5 * 1024 * 1024;    //  总开销5MB    };    return self;}-(void)downloadDataForURL:(NSURL *)url {    NSData *cachedData = [_cache objectForKey:url];    if (cachedData) {        //[self useData:cachedData];    } else {        EOCNetworkFetcher *fetcher = [[EOCNetworkFetcher alloc] initWithURL:url];        [fetcher startWithCompletionHandler:^(NSData *data) {            [_cache setObject:data forKey:url cost:data.length];            //[self useData];        }];    }}@end
 在本例中,可缓存对象总数设置为100,总开销上限设置为5MB。
 还有一个类是NSPurgeableData,和NSCache搭配使用,此类事NSMutableData的子类,实现了NSDiscardableContent协议。当系统资源紧张时可以把保存的NSPurgeableData对象的那块内存释放掉。NSDiscardableContent协议定义了isContentDiscarded的方法,查询相关内存是否已被释放。
 如果需要访问某个NSPurgeableData对象,可以调用beginContentAsscee方法,告诉它现在还不应该丢弃自己所占的内存。用完后调用endContentAccess方法,告诉它在必要的时候可以丢弃自己所占的内存。
 将NSPurgeableData对象加入NSCache,当该对象被丢弃时,也会自动从系统中移除,通过NSCache的evictsObjectsWithDiscardedContent属性,可以开关此功能。
 上面的例子可用NSPurgeableData改写:
-(void)downloadDataForURLTwo:(NSURL *)url {    NSPurgeableData *cachedData = [_cache objectForKey:url];    if (cachedData) {        [cachedData beginContentAccess];        // [self useData:cacheData];        [cachedData endContentAccess];    } else {        EOCNetworkFetcher *fetcher = [[EOCNetworkFetcher alloc] initWithURL:url];        [fetcher startWithCompletionHandler:^(NSData *data) {            NSPurgeableData *purgeableData = [NSPurgeableData dataWithData:data];            [_cache setObject:purgeableData forKey:url cost:purgeableData.length];            //[self useData:purgeableData];            [purgeableData endContentAccess];        }];    }}
 注意:创建好NSPurgeableData后,其purge计数会多1,不用先执行beginContentAsscee方法,使用完后需要执行endContentAccess方法。
 
 总结:
 1.NSCache可以提供自动删减缓存功能,而且保证线程安全,与字典不同,不会拷贝键。
 2.NSCache可以设置缓存上限,限制对象个数和总缓存开销。定义了删除缓存对象的时机。这个机制只对NSCache起到指导作用,不会一定执行。
 3.NSPurgeableData搭配NSCache使用,可以自动清除数据。
 4.只有那种“重新计算很费劲”的数据才值得放入缓存。

阅读全文
0 0
原创粉丝点击