Objective-C的緩衝架構EGOCache在iOS App開發中的使用_IOS

來源:互聯網
上載者:User

EGOCache簡介

EGOCache is a simple, thread-safe key value cache store. It has native support for NSString, UI/NSImage, and NSData, but can store anything that implements <NSCoding>. All cached items expire after the timeout, which by default, is one day.
翻譯過來就是:EGOCache一個簡單、安全執行緒的基於 key-value 的緩衝架構,原生支援NSString、UI/NSImage、和NSData,也支援儲存任何實現協議的類,可以設定緩衝到期時間,預設是1天。

EGOCache只有一個類,EGOCache.h和EGOCache.m兩個檔案。用法也比較容易掌握,仔細研究一下EGOCache.h的方法,很快就可以上手。

EGOCache只提供了磁碟緩衝,沒有提供記憶體緩衝。同時,也提供了清理緩衝的方法:

複製代碼 代碼如下:

- (void)clearCache;

EGOCache還提供了判斷緩衝是否存在的方法:
複製代碼 代碼如下:

- (BOOL)hasCacheForKey:(NSString* __nonnull)key;

通過Cocoapods直接加入項目

直接在你的項目的Podfile加入下面一行:

複製代碼 代碼如下:

pod 'EGOCache'

然後執行:
複製代碼 代碼如下:

$ pod update

EGOCache用法

用EGOCache緩衝NSString

儲存:

複製代碼 代碼如下:

NSString *saveString = @"把我儲存起來吧";
[[EGOCache globalCache] setString:saveString forKey:[NSString stringWithFormat:@"EGOImageLoader-%lu", (unsigned long)[saveString hash]] withTimeoutInterval:24*60*60];

讀取:
複製代碼 代碼如下:

NSString *getSaveString = [[EGOCache globalCache] stringForKey:[NSString stringWithFormat:@"EGOImageLoader-%lu", (unsigned long)[@"SaveString" hash]]];

是不是感覺跟NSDictionary很相似,確實,前面我們說了EGOCache是基於key-value 的緩衝架構。

用EGOCache緩衝UIImage

儲存:

複製代碼 代碼如下:

 UIImage *saveImage = [UIImage imageNamed:@"iOSDevTip"];
[[EGOCache globalCache] setImage:saveImage forKey:[NSString stringWithFormat:@"EGOImageLoader-%lu", (unsigned long)[@"SaveImage" hash]] withTimeoutInterval:24*60*60];

讀取:
複製代碼 代碼如下:

UIImage *getSaveImage = [[EGOCache globalCache] imageForKey:[NSString stringWithFormat:@"EGOImageLoader-%lu", (unsigned long)[@"SaveImage" hash]]];

用EGOCache緩衝NSData

儲存:

複製代碼 代碼如下:

NSData *saveData = [NSData data];
[[EGOCache globalCache] setData:saveData forKey:[NSString stringWithFormat:@"EGOImageLoader-%lu", (unsigned long)[@"SaveData" hash]] withTimeoutInterval:24*60*60];

讀取:
複製代碼 代碼如下:

UIImage *getSaveData = [[EGOCache globalCache] dataForKey:[NSString stringWithFormat:@"EGOImageLoader-%lu", (unsigned long)[@"SaveData" hash]]];

EGOCache如何檢測緩衝時間到期
EGOCache可以設定緩衝到期時間,預設是1天。查看了一下EGOCache源碼,設定預設時間:

複製代碼 代碼如下:

    [self setDefaultTimeoutInterval:86400];
    //86400 = 24 * 60 * 60 剛好是一天時間。

EGOCache為什麼要提供設定緩衝到期時間呢?或者說設定緩衝到期時間有什麼好處呢?我覺得最大的好處就是可以定時清除緩衝。可以設定某一項的緩衝時間,很方便管理緩衝。

那麼問題來了:

  • EGOCache是怎麼檢測緩衝到期時間的呢?
  • 檢測到時間到期之後,什麼時候觸發刪除快取項目的?

帶著這兩個問題,我們來繼續分析。

你會怎麼實現

記得在公司裡,老闆經常會舉這樣的例子:

某某同志,剛來我們公司的時候,遇到問題就知道抱怨。從來不知道去思考怎麼解決,只知道把問題拋給領導。工作半年下來,成長了很多。現在碰到問題,不僅把問題拋出來,而且還提供了自己的解決方案...
類似的例子,相信大家都聽過。同樣,既然前面我們提出這兩個問題,我們也先來思考一下,如果我們來做該怎麼解決?

如果讓我來寫的話,我腦海裡初步實現方法有幾個:

  • 通過定時器來輪詢,每隔一段時間檢測一次。
  • 寫一個while迴圈來檢測。
  • 每次去讀取快取項目的時候,判斷緩衝時間有沒有到期。沒到期,就返回讀取的快取項目;否則,返回nil。
  • 當然,還有一些方法,不一一例舉了。仔細想想,這些方法弊端很容易顯露出來。

為了小小的緩衝時間,就用定時器輪詢,顯然是資源浪費
跟方法1差不多。
每次讀取的時候判斷是否到期,如果一直不讀取,app的緩衝會越來越大,也不可取。
這些方法都被排除了,還有好的方法嗎?繼續往下看:

EGOCache是怎麼實現的?

仔細查看EGOCache源碼,發現在initWithCacheDirectory:方法裡,每次初始化EGOCache執行個體對象的時,會遍曆一遍plist檔案中所有已存在的快取項目,拿每個快取項目的時間和目前時間作比較,快取項目到期時間早於目前時間,則刪除對應快取檔案,並刪除 plist 檔案中對應 key 的記錄。

具體實現代碼如下:

讀取快取項目資訊

複製代碼 代碼如下:

_cacheInfo = [[NSDictionary dictionaryWithContentsOfFile:cachePathForKey(_directory, @"EGOCache.plist")] mutableCopy];
if(!_cacheInfo) {
    _cacheInfo = [[NSMutableDictionary alloc] init];
}

擷取目前時間的NSTimeInterval
複製代碼 代碼如下:

NSTimeInterval now = [[NSDate date] timeIntervalSinceReferenceDate];

聲明removedKeys儲存到期的快取項目對應的key
複製代碼 代碼如下:

NSMutableArray* removedKeys = [[NSMutableArray alloc] init];

遍曆快取項目資訊並判斷緩衝時間
複製代碼 代碼如下:

for(NSString* key in _cacheInfo) {
    //判斷快取項目到期時間是否早於目前時間
    if([_cacheInfo[key] timeIntervalSinceReferenceDate] <= now) {
        //如果快取項目到期時間早於目前時間,移除快取項目
        [[NSFileManager defaultManager] removeItemAtPath:cachePathForKey(_directory, key) error:NULL];
        //把到期的快取項目對於的key儲存到removedKeys裡面
        [removedKeys addObject:key];
    }
}

刪除到期快取項目對於的key
複製代碼 代碼如下:

[_cacheInfo removeObjectsForKeys:removedKeys];

看到這些,是不是覺得人家思路特牛叉,反正,我是覺得這個作者不簡單。到這一步就解決了嗎?

EGOCache還做了什嗎?

細心的童鞋會發現:EGOCache是個單列類,也就是說整個程式應用周期只初始化一次。

複製代碼 代碼如下:

+ (instancetype)globalCache {
    static id instance;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[[self class] alloc] init];
    });
    return instance;
}


每次初始化的時候去判斷了快取項目是否到期,這樣做非常正確。思考一個情境:

使用者開啟app,EGOCache被初始化,並判斷了快取項目是否到期。
如果剛好有一些快取項目在EGOCache被初始化之後到期。這個時候我們依然可以讀到這個快取項目。這就不對了。
繼續分析EGOCache源碼發現,EGOCache在讀取一個快取項目的時候,先判斷快取項目是否存在,然後讀取快取項目(注意:是讀取EGOCache初始化的時候沒有到期的快取項目,並沒有說現在沒有到期),最後去判斷讀取到的快取項目跟目前時間相比是否到期.

具體實現如下:

複製代碼 代碼如下:

- (BOOL)hasCacheForKey:(NSString*)key {
    //讀取EGOCache初始化的時候沒有到期的快取項目
    NSDate* date = [self dateForKey:key];
    if(date == nil) return NO;
    //判斷讀取到的快取項目當前是否到期
    if([date timeIntervalSinceReferenceDate] < CFAbsoluteTimeGetCurrent()) return NO;
    return [[NSFileManager defaultManager] fileExistsAtPath:cachePathForKey(_directory, key)];
}
- (NSDate*)dateForKey:(NSString*)key {
    __block NSDate* date = nil;

    dispatch_sync(_frozenCacheInfoQueue, ^{
        date = (self.frozenCacheInfo)[key];
    });

    return date;
}


EGOCache檢測緩衝時間到期的思路值得學習,以後遇到類似情境,完全可以借鑒。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.