50、构建缓存时选用NSCache而非NSDictionary

NSCache

  1. 当系统资源将耗尽时,自动删减缓存(若用普通字典,需要自己写挂钩,在“低内存”警告时通知删减缓存)。

  2. 还会先行删减“最久未使用的”对象。

  3. 不会“拷贝”键,而是会“保留”它(当键不支持拷贝时很合适)。

  4. 是线程安全的。

  5. 可以设置缓存 对象总数 和 “总开销”。

NSCache搭配NSPureableData使用:

typedef void(^EOCNetworkFetcherCompletionHander)(NSData *data);
NSCache *_cache;
- (instancetype)init {
  self = [super init];
  if (self) {
    _cache = [NSCache new];
    _cache.countLimit = 100; // 100 URLs
    _cache.totalCostLimit = 5 * 1024 * 1024; // 5MB
  }
  return self;
}
- (void)downloadDataForUrl:(NSURL *)url {
  NSPurgeableData *cachedData = [_cache objectForKey:url];
  if (cachedData) { // Cache hit
//    cachedData.isContentDiscarded // 相关内存是否已释放
    [cachedData beginContentAccess]; // 告诉它不应丢弃自己所占用的内存
    [self useData:cachedData];
    [cachedData endContentAccess]; // 告诉它在必要时可以丢弃自己所占用的内存
  } else { // Cache miss
    EOCNetworkFetcher *fetcher = [[EOCNetworkFetcher alloc] initWithURL:url];
    [fetcher startWithCompletionHander:^(NSData *data){
      NSPurgeableData *purgeableData = [NSPurgeableData dataWithData:data];
      [_cache setObject:purgeableData forKey:url cost:purgeableData.length];
      [self useData:purgeableData];
      [purgeableData endContentAccess];
    }];
  }
}

要点:

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

  • 可以给NSCache对象设置上限,用以限制缓存中的对象总个数,但是绝不要把这些设置当成可靠的“硬限制”,他们仅对NSCache起指导作用

  • NSPurgeableDataNSCache搭配使用,可实现自动清楚数据的功能。及当NSPurgeableData对象所占用内存被系统丢弃时,该对象自身也会从缓存中移除

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

Last updated

Was this helpful?