iOS源码解析—YYCache(概述)
概述
YYCache是一个用来封装客户端缓存功能的库,实现了二级缓存的机制,即同时具备内存缓存和硬盘缓存的功能。
文件结构
YYCache主要分为YYCache、YYDiskCache和YYMemoryCache三个类,YYDiskCache实现了硬盘缓存的功能,YYMemoryCache实现了内存缓存的功能,YYCache类提供了通用的缓存存取的方法,内部调用YYMemoryCache和YYDiskCache的方法。
YYCache
下面是YYCache类的代码注释:
@interface YYCache : NSObject
@property (copy, readonly) NSString *name; //缓存路径名
@property (strong, readonly) YYMemoryCache *memoryCache; //内存缓存
@property (strong, readonly) YYDiskCache *diskCache; //硬盘缓存
//初始化
- (nullable instancetype)initWithName:(NSString *)name; //根据名称初始化
- (nullable instancetype)initWithPath:(NSString *)path; //根据路径初始化
+ (nullable instancetype)cacheWithName:(NSString *)name; //根据名称初始化
+ (nullable instancetype)cacheWithPath:(NSString *)path; //根据路径初始化
- (instancetype)init UNAVAILABLE_ATTRIBUTE;
+ (instancetype)new UNAVAILABLE_ATTRIBUTE;
//缓存中是否包含key对应的数据
- (BOOL)containsObjectForKey:(NSString *)key;
- (void)containsObjectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key, BOOL contains))block;
//根据key查找并返回缓存中对应的数据
- (nullable id<NSCoding>)objectForKey:(NSString *)key;
- (void)objectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key, id<NSCoding> object))block;
//想缓存中存入数据,设置key
- (void)setObject:(nullable id<NSCoding>)object forKey:(NSString *)key;
- (void)setObject:(nullable id<NSCoding>)object forKey:(NSString *)key withBlock:(nullable void(^)(void))block;
//删除key对应的缓存数据
- (void)removeObjectForKey:(NSString *)key;
- (void)removeObjectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key))block;
//清空所有缓存数据
- (void)removeAllObjects;
- (void)removeAllObjectsWithBlock:(void(^)(void))block;
- (void)removeAllObjectsWithProgressBlock:(nullable void(^)(int removedCount, int totalCount))progress endBlock:(nullable void(^)(BOOL error))end;
@end
YYCache主要提供了一系列操作缓存的方法,主要分为初始化、查找、存、取、删除几种。下面分别简单分析一下:
-
初始化
核心方法是initWithName:name,该方法首先将将文件名name拼接在沙盒cache目录下面,作为YYCache创建缓存的路径,然后调用initWithPath:方法:
- (instancetype)initWithPath:(NSString *)path { if (path.length == 0) return nil; YYDiskCache *diskCache = [[YYDiskCache alloc] initWithPath:path]; //创建硬盘缓存 if (!diskCache) return nil; NSString *name = [path lastPathComponent]; YYMemoryCache *memoryCache = [YYMemoryCache new]; //创建内存缓存 memoryCache.name = name; self = [super init]; _name = name; //缓存目录名称 _diskCache = diskCache; _memoryCache = memoryCache; return self; }
该方法根据路径path创建硬盘缓存对象diskCache,然后根据目录名称创建内存缓存对象memoryCache。
-
查找
containsObjectForKey:方法判断内存或者硬盘中是否存在key对应的数据,代码如下:
- (BOOL)containsObjectForKey:(NSString *)key { return [_memoryCache containsObjectForKey:key] || [_diskCache containsObjectForKey:key]; }
可能存在数据只在内存或者硬盘中出现的情况,所以逻辑上是或的关系。
-
存
setObject: forKey:方法分别调用_diskCache和_memoryCache对象进行硬盘和内存的存储。
- (void)setObject:(id<NSCoding>)object forKey:(NSString *)key { [_memoryCache setObject:object forKey:key]; [_diskCache setObject:object forKey:key]; }
-
取
objectForKey:方法首先从内存中取数据,如果取不到,再从硬盘中取数据,并且把取到的数据存进内存中。
- (id<NSCoding>)objectForKey:(NSString *)key { id<NSCoding> object = [_memoryCache objectForKey:key]; if (!object) { object = [_diskCache objectForKey:key]; if (object) { [_memoryCache setObject:object forKey:key]; } } return object; }
由于从硬盘中取需要I/O操作,所以内存中发现有数据,直接返回的逻辑在性能上会提升。
-
删除
removeObjectForKey:方法分别调用_memoryCache和_diskCache的删除方法分别从内存和硬盘中删除数据。
- (void)removeObjectForKey:(NSString *)key { [_memoryCache removeObjectForKey:key]; [_diskCache removeObjectForKey:key]; }
总结
通过代码分析,YYCache类实际都是调用_memoryCache和_diskCache来进行内存和硬盘的存取等操作,下文分别分析YYMemoryCache和YYDiskCache类。