美文网首页编写高质量代码的52个有效方法
52个有效方法(50) - 构建缓存时,选用NSCache而非N

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

作者: SkyMing一C | 来源:发表于2018-10-09 17:20 被阅读15次
    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. 如果缓存使用得当,那么应用程序的响应速度就能提高。只有那种“重新计算起来很费事的”数据,才值得放入缓存,比如那些需要从网络获取或从磁盘读取的数据。

    相关文章

      网友评论

        本文标题:52个有效方法(50) - 构建缓存时,选用NSCache而非N

        本文链接:https://www.haomeiwen.com/subject/wwzpnftx.html