iOS緩存框架YYCache的學習

先上源碼鏈接https://github.com/ibireme/YYCache

簡介

YYCache 是提供用用戶使用的對象,內(nèi)部對 YYMemoryCacheYYDiskCache功能的整合封裝。為 YYMemoryCache提供了多線程功能,而YYDiskCache對象本身內(nèi)部封裝了異步讀寫功能。

YYCache分為兩部分:磁盤緩存、內(nèi)存緩存。

  • 內(nèi)存緩存(YYMemoryCache)
    存儲的單元是_YYLinkedMapNode,除了key和value外,還存儲了它的前后Node的地址_prev、_next。整個實現(xiàn)基于_YYLinkedMap,它是一個雙向鏈表,除了存儲了字典_dic外,還存儲了頭結(jié)點和尾節(jié)點。它實現(xiàn)的功能很簡單:有新數(shù)據(jù)了插入鏈表頭部,訪問過的數(shù)據(jù)結(jié)點移到頭部,內(nèi)存緊張時把尾部的結(jié)點移除。就這樣實現(xiàn)了淘汰算法。因為內(nèi)存訪問速度很快,鎖占用的時間少,所以用的速度最快的OSSpinLockLock

  • 硬盤緩存(YYDiskCache)
    采用 文件和數(shù)據(jù)庫相互配合的方式。有一個參數(shù)inlineThreshold(默認值20KB),小于它存數(shù)據(jù)庫,大于它存文件,能獲得效率的提高。key:path,value:cache存儲在NSMapTable里,根據(jù)path獲得cache,進行一系列的set、get、remove操作。
    更底層的是YYKVStorage,它能直接對sqlite和文件系統(tǒng)進行讀寫。每次內(nèi)存超過限制時,select key, filename, size from manifest order by last_access_time desc limit ?1會根據(jù)時間排序,來刪除最近不常用的數(shù)據(jù)。硬盤訪問的時間比較長,如果用OSSpinLockLock鎖會造成CPU消耗過大,所以用的dispatch_semaphore_wait來做。

基本使用

一、同步方式存取

1.初始化緩存對象

- (nullable instancetype)initWithName:(NSString *)name;
- (nullable instancetype)initWithPath:(NSString *)path;
+ (nullable instancetype)cacheWithName:(NSString *)name;
+ (nullable instancetype)cacheWithPath:(NSString *)path;

這幾個方法功能是一致的。
如:

YYCache *cache = [[YYCache alloc] initWithName:@"APP_CACHE"];

2.存

id data;  // 需要存儲的數(shù)據(jù)

YYCache *cache = [YYCache cacheWithName:@"APP_CACHE"];
[cache setObject:data forKey:@"data_key"];

首先調(diào)用內(nèi)存緩存設置緩存API(setObject:forKey:),然后調(diào)用磁盤緩存異步設置API(setObject:forKey:)

3.判斷是否有緩存

YYCache *cache = [YYCache cacheWithName:@"APP_CACHE"];
BOOL isContains = [cache containsObjectForKey:@"data_key"]

先去內(nèi)存緩存中查找,如果沒有查找就去磁盤緩存中找,找到就返回 YES。

4.取

YYCache *cache = [YYCache cacheWithName:@"APP_CACHE"];
id data = [cache objectForKey:@"data_key"];

先去內(nèi)存緩存中查找,有就返回。如果沒有就去磁盤緩存中找,找到了,先把緩存存入內(nèi)存緩存中,然后再返回結(jié)果。

5.移除緩存

YYCache *cache = [YYCache cacheWithName:@"APP_CACHE"];
//根據(jù)key移除緩存
    [cache removeObjectForKey:@"data_key"];
//移除APP所有緩存
    [cache removeAllObjects];

首先調(diào)用內(nèi)存緩存的刪除接口(removeObjectForKey:),然后調(diào)用磁盤緩存的刪除接口(removeObjectForKey:)

二、異步方式

YYCache *cache = [YYCache cacheWithName:@"APP_CACHE"];
id data;  // 需要存儲的數(shù)據(jù)
[cache setObject:data forKey:@"data_key" withBlock:^{
    NSLog(@"save sucess");
}];

首先調(diào)用內(nèi)存緩存設置緩存API(setObject:forKey:),然后調(diào)用磁盤緩存異步設置API(setObject:forKey:)

判斷緩存是否存在

[cache containsObjectForKey:@"data_key" withBlock:^(NSString * _Nonnull key, BOOL contains) {
    if(contains){
        //...
    }
}];

同步在內(nèi)存中查找緩存,如果找到了,使用異步返回。如果沒找到,就調(diào)用磁盤緩存的異步查找 API,并把查找結(jié)果異步回調(diào)。

[cache objectForKey:@"data_key" withBlock:^(NSString * _Nonnull key, id<NSCoding>  _Nonnull object) {
    if(object){
        // 獲取成功
    }
}];

同步在內(nèi)存中查找,如果找到了,使用異步返回。如果沒找到,就調(diào)用磁盤緩存的異步查找 API,找到了,先把緩存存入內(nèi)存緩存中,然后再返回結(jié)果。

移除

//根據(jù)key移除緩存
[cache removeObjectForKey:@"data_key" withBlock:^(NSString * _Nonnull key) {
    NSLog(@"removeObjectForKey: %@",key);
}];
//移除APP所有緩存
[cache removeAllObjectsWithBlock:^{
    NSLog(@"removeAllObjects sucess");
}];

首先調(diào)用內(nèi)存緩存刪除接口(removeObjectForKey:),然后調(diào)用磁盤緩存異步刪除接口(removeObjectForKey:withBlock:)

移除所有緩存帶進度

    [cache removeAllObjectsWithProgressBlock:^(int removedCount, int totalCount) {
        NSLog(@" 已移除數(shù) :%d , 移除總數(shù): %d",removedCount,totalCount);
    } endBlock:^(BOOL error) {
        if(!error){
            NSLog(@"sucess");
        }else{
            NSLog(@"error");
        }
    }];

緩存/ 磁盤單獨操作

YYCache *cache = [YYCache cacheWithName:@"APP_CACHE"];

YYDiskCache *diskCache = cache.diskCache;
YYMemoryCache *memoryCache = cache.memoryCache;

存取方法與cache 一致

緩存LRU清理

LRU(Least Recently Used)算法翻譯過來就是“最近最少使用”。LRU緩存原理,簡單的說就是,緩存一定量的數(shù)據(jù),當超過設定的閾值時就把一些過期的數(shù)據(jù)刪除掉。

比如緩存10000條數(shù)據(jù),當數(shù)據(jù)小于10000時可以隨意添加;當超過10000時,就需要把新的數(shù)據(jù)添加進來,同時要把過期數(shù)據(jù)刪除,以確保我們最大緩存10000條。
那怎么確定刪除哪條過期數(shù)據(jù)?采用LRU算法實現(xiàn)的話就是將最老的數(shù)據(jù)刪掉。

YYCache磁盤LRU清理并不是及時清理,而是后臺開啟一個定時任務進行RLU清理操作,定時默認是60s。

YYCache *yyCache=[YYCache cacheWithName:@"LCJCache"];
[yyCache.memoryCache setCountLimit:50];  //內(nèi)存最大緩存數(shù)據(jù)個數(shù)
[yyCache.memoryCache setCostLimit:1*1024];//內(nèi)存最大緩存開銷 目前這個毫無用處
[yyCache.diskCache setCostLimit:10*1024];//磁盤最大緩存開銷
[yyCache.diskCache setCountLimit:50];    //磁盤最大緩存數(shù)據(jù)個數(shù)
[yyCache.diskCache setAutoTrimInterval:60];//設置磁盤lru動態(tài)清理頻率 默認 60秒

相關資料

https://blog.ibireme.com/2015/10/26/yycache/
https://www.cnblogs.com/machao/p/7086675.html
http://www.itdecent.cn/p/5a63bdca4a21

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容