陈斌彬的技术博客

Stay foolish,stay hungry

EGOCache源码解析

今天说说一款叫 EGOCache 的开源项目,一个简单、线程安全的基于 key-value 的缓存框架,原生支持 NSStringUI/NSImage、和 NSData,也支持储存任何实现 <NSCoding> 协议的类,可以设定缓存过期时间,默认是 1 天;ARC、基于 Block,同时支持 iOS 和 OSX 平台。

Fast Caching for Objective-C (iPhone & Mac Compatible)

EGOCache 是 Enormego 团队的开源作品,Enormego 在 Github 上贡献了众多开源项目,大家很可能用过 EGOTableViewPullRefresh ,它就是出自 Enormego 之手,可不知为何 EGOTableViewPullRefresh 在两年前就已经停止了更新;不过不用担心,今天本文所说的 EGOCache 还在保持着更新。

结构分析

EGOCache 保持很轻盈的体积,只有一个类,包括 EGOCache.hEGOCache.m 两个文件,和最基本的操作,也很方便我们学习。

分区

提供了一个缓存分区的概念(姑且叫分区吧),可对复杂的项目进行缓存分区,基于文件的各个分区的缓存各不受影响,一个 EGOCache 实例就对应一个分区。可以让稍复杂的应用场景对不同的数据进行分类缓存,便于管理和统计。

建立分区

如果想要新建一个分区,可以使用 initWithCacheDirectory: 构造方法指定一个缓存目录来创建一个 EGOCache 实例,如果分区已存在,则会直接使用。

全局分区

EGOCache 贴心地提供了一个全局 EGOcache 单例,也就是一个默认分区,方便一些简单情况下的快速使用。调用 globalCache 实例方法就能获取到一个单例实例,就是所提供的默认缓存分区。

储存方式

EGOCache 采用磁盘储存方式缓存所有数据,且并没有提供内存缓存,所以如果你需要频繁读取某些缓存,为了加快读取速度和磁盘开销还是建议自己在内存中缓存一下。

上文说到分区的概念,每一个分区就对应一个 EGOcache 实例,同时对应一个 缓存目录,目录中就包含唯一一个 .plist 文件,这个 plist 文件中就存放了缓存文件对应的 key 和该项的 过期时间,所以每个缓存目录结构大致如下:

MyCache
    MyCache.plist
    _abc
    _def

过期

每缓存一个项,都可以单独为其设定一个过期时间,那检查这个过期时间并做删除操作的事件是在哪里触发的呢?

经过对源码的翻阅,在 initWithCacheDirectory: 方法里,即每次初始化实例对象的时候会扫描一遍 plist 文件中记录的所有已存在的缓存项,并和当前时间作比较,过期时间早于了当前时间则删除对应缓存文件,并删除 plist 文件中对应 key 的记录。

线程

大量使用了基于 GCD 的异步操作,在 EGOCache 类的构造中为每个实例维护了 3 个 GCD 队列:

dispatch_queue_t _cacheInfoQueue;
dispatch_queue_t _frozenCacheInfoQueue;
dispatch_queue_t _diskQueue;

从名字即可看到不同的队列对应不同的缓存相关操作,为了互不冲突。

安装

已加入 Cocoapods 豪华午餐,即刻享用:

pod 'EGOCache'

Resourece Reference