52个有效方法(50) - 构建缓存时,选用NSCache而非NSDictionary

NSCache

NSCache是苹果官方提供的缓存类,用法与NSMutableDictionary的用法很相似,在AFNetworkingSDWebImage中,使用它来管理缓存。

  • 当系统资源将要耗尽时,它可以自动删除缓存(NSCache会先行删减“最久未使用的”对象,)。

  • NSCache并不会拷贝key,而是会保留它,因为大多数key值都是由不支持拷贝的对象来充当的。

  • NScache是线程安全的,在多线程操作中,不需要对Cache加锁。

NSCache的属性
  • countLimit:能够缓存对象的最大数量,默认值是0(没有限制)。

  • totalCostLimit :缓存空间的最大成本,超出上限会自动回收对象。默认值是0(没有限制)。

  • 当超出缓存最大成本或数量时,NSCache会把前面的数据即最开始存的给清除掉。

  • evictsObjectsWithDiscardedContent:表示是否回收废弃的内容,默认值是YES(自动回收)。

NSCache的方法
  • objectForKey:返回与键值关联的对象。

  • setObject: forKey:在缓存中设置指定键名对应的值。与可变字典不同的是,缓存对象不会对键名做copy操作。

  • setObject: forKey: cost:在缓存中设置指定键名对应的值,并且指定该键值对的成本。成本cost用于计算记录在缓冲中所有对象的总成本。当出现内存警告,或者超出缓存的成本上限时,缓存会开启一个回收过程,删除部分元素。

  • removeObjectForKey:删除缓存中指定键名的对象。

  • removeAllObjects:删除缓存中的所有对象。

委托方法
  • cache: willEvictObject:缓存将要删除对象时调用,不能在此方法中修改缓存。仅仅用于后台的打印,以便于调试。
#import "ViewController.h"

@interface ViewController()<NSCacheDelegate>
@property (nonatomic, strong) NSCache *myCache;
@end
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    
    for (int i =0 ; i< 5; i++) {
        // 向缓存中添加对象
        NSString *str = [NSString stringWithFormat:@"cache - %d", I];
        [self.myCache setObject:str forKey:@(i)];
    }
    for (int i=0 ; i< 5; i++) {
        NSLog(@"%@", [self.myCache objectForKey:@(i)]);
    }
}

-(NSCache *)myCache
{
    if (_myCache == nil) {
        _myCache = [[NSCache alloc] init];
        _myCache.countLimit = 3;
        _myCache.delegate = self;
    }
    return _myCache;
}

#pragma mark- delegate
-(void)cache:(NSCache *)cache willEvictObject:(id)obj
{
    NSLog(@"要删除的对象obj-------------%@", obj);
}
@end
NSPurgeableData
  • NSMutableData的子类,且实现了NSDiscardableContent协议。

  • 当系统资源紧张时,可以把保存NSPurgeableData对象的那块内存释放掉。

  • 调用beginContentAccess,说明现在还不应丢弃NSPurgeableData所占的内存。

  • 调用endContentAccess,说明在必要时可以丢弃NSPurgeableData所占的内存。

  • beginContentAccess与endContentAccess类似引用计数的方式,当对象的“引用计数”为0才可以被丢弃。

  • 如果缓存使用得当,那么应用程序的响应速度就能提高,只有那种“只要计算起来很难费事的”数据,才值得放入缓存,比如那些需要从网络获取或从磁盘读取的数据。

#import "ViewController.h"

@interface ViewController ()
{
    NSCache *_cache;
}
@end

@implementation ViewController

- (instancetype)init
{
    self = [super init];
    if (self) {
        _cache = [[NSCache alloc] init];
        _cache.countLimit = 100;
        _cache.totalCostLimit = 5 * 1024 * 1024;
    }
    return self;
}

- (void)downloadWithURL:(NSURL *)url
{
    NSPurgeableData *cacheData = [_cache objectForKey:url];
    if (cacheData) {
        [cacheData beginContentAccess];
        
        [self useData:cacheData];
        
        [cacheData endContentAccess];
    }else{
        //network init
        //network block -->data
        {
            NSPurgeableData *purgeableData = [[NSPurgeableData alloc] initWithData:data];
            [_cache setObject:purgeableData forKey:url cost:purgeableData.length];
            
            [self useData:cacheData];
            
            [purgeableData endContentAccess];
        }
    }
}

- (void)useData:(NSPurgeableData *)data {}

@end
要点
  1. 实现缓存时应选用NSCache而非NSDictionary对象。因为NSCache可以提供优雅的自动删减功能,而且是“线程安全的”,此外,它与字典不同,并不会拷贝键。

  2. 可以给NSCache对象设置上限,用以限制缓存中的对象总个数及“总成本”,而这些尺度则定义了缓存删减其中对象的时机。但是绝对不要把这些尺度当成可靠的“硬限制”,他们仅对NSCache起知道作业。

  3. 将NSPurgeableData与NSCache搭配使用,可实现自动清除数据的功能,也就是说,当NSPurgeableData对象所占内存为系统所丢弃时,该对象自身也会从缓存中移除。

  4. 如果缓存使用得当,那么应用程序的响应速度就能提高。只有那种“重新计算起来很费事的”数据,才值得放入缓存,比如那些需要从网络获取或从磁盘读取的数据。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352

推荐阅读更多精彩内容