YYCache源碼分析(一)

YYCache源碼分析(一)

文/漢斯哈哈哈(簡書作者)
原文鏈接:http://www.reibang.com/p/b8dcf6634fab

iOS 開發(fā)中總會用到各種緩存,YYCache或許是你最好的選擇窿吩。性能上有優(yōu)勢,用法也很簡單铝侵。作者ibireme曾經(jīng)對比過同類輪子:http://blog.ibireme.com/2015/10/26/yycache/

1.簡單架構(gòu)圖

2.YYCache.h方法分析

@interface YYCache : NSObject
// 讀取當前數(shù)據(jù)庫名稱
@property (copy, readonly) NSString *name;

// memoryCache內(nèi)存緩存,diskCache文件緩存
@property (strong, readonly) YYMemoryCache *memoryCache;
@property (strong, readonly) YYDiskCache *diskCache;

// 可通過下面四種方法來實例化YYCache對象
- (nullable instancetype)initWithName:(NSString *)name;
- (nullable instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER;
+ (nullable instancetype)cacheWithName:(NSString *)name;
+ (nullable instancetype)cacheWithPath:(NSString *)path;

// 禁止通過下面兩個方式實例化對象
- (instancetype)init UNAVAILABLE_ATTRIBUTE;
+ (instancetype)new __attribute__((unavailable("new方法不可用,請用initWithName:")));

// 通過key判斷是否緩存了某個東西温治,第二個法是異步執(zhí)行,異步回調(diào)
- (BOOL)containsObjectForKey:(NSString *)key;
- (void)containsObjectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key, BOOL contains))block;

// 讀--通過key讀取緩存养铸,第二個法是異步執(zhí)行,異步回調(diào)
- (nullable id<NSCoding>)objectForKey:(NSString *)key;
- (void)objectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key, id<NSCoding> object))block;

// 增雁芙、改--緩存對象(可緩存遵從NSCoding協(xié)議的對象)轧膘,第二個法是異步執(zhí)行,異步回調(diào)
- (void)setObject:(nullable id<NSCoding>)object forKey:(NSString *)key;
- (void)setObject:(nullable id<NSCoding>)object forKey:(NSString *)key withBlock:(nullable void(^)(void))block;

// 刪--刪除緩存
- (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

這些語法:參考外鏈學習:
NS_DESIGNATED_INITIALIZER

  • (instancetype)new attribute((unavailable("new方法不可用,請用initWithName:")));

3.YYCache使用

// 0.初始化YYCache
YYCache *cache = [YYCache cacheWithName:@"mydb"];
// 1.緩存普通字符
[cache setObject:@"漢斯哈哈哈" forKey:@"name"];
NSString *name = (NSString *)[cache objectForKey:@"name"];
NSLog(@"name: %@", name);
// 2.緩存模型
[cache setObject:(id<NSCoding>)model forKey:@"user"];
// 3.緩存數(shù)組
NSMutableArray *array = @[].mutableCopy;
for (NSInteger i = 0; i < 10; i ++) {
    [array addObject:model];
}
// 異步緩存
[cache setObject:array forKey:@"user" withBlock:^{
    // 異步回調(diào)
    NSLog(@"%@", [NSThread currentThread]);
    NSLog(@"array緩存完成....");
}];
// 延時讀取
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    // 異步讀取
    [cache objectForKey:@"user" withBlock:^(NSString * _Nonnull key, id<NSCoding>  _Nonnull object) {
        // 異步回調(diào)
        NSLog(@"%@", [NSThread currentThread]);
        NSLog(@"%@", object);
    }];
});

打油酶省:

2016-06-09 11:35:44.069 YYCache源碼分析[13546:949048] <NSThread: 0x7ffd43f14840>{number = 2, name = (null)}
2016-06-09 11:35:44.069 YYCache源碼分析[13546:949048] array緩存完成....
2016-06-09 11:35:44.386 YYCache源碼分析[13546:949052] <NSThread: 0x7ffd43e01900>{number = 3, name = (null)}
2016-06-09 11:35:44.386 YYCache源碼分析[13546:949052] (
    "<UserModel: 0x7ffd44014310>",
    "<UserModel: 0x7ffd44014310>",
    "<UserModel: 0x7ffd44014310>",
    "<UserModel: 0x7ffd44014310>",
    "<UserModel: 0x7ffd44014310>",
    "<UserModel: 0x7ffd44014310>",
    "<UserModel: 0x7ffd44014310>",
    "<UserModel: 0x7ffd44014310>",
    "<UserModel: 0x7ffd44014310>",
    "<UserModel: 0x7ffd44014310>"
)
// 緩存實現(xiàn)谎碍,默認同時進行內(nèi)存緩存與文件緩存
- (void)setObject:(id<NSCoding>)object forKey:(NSString *)key {
    [_memoryCache setObject:object forKey:key];
    [_diskCache setObject:object forKey:key];
}
// 如果只想內(nèi)存緩存,可以直接調(diào)用`memoryCache`對象
YYCache *cache2 = [YYCache cacheWithName:@"mydb"];
[cache2.memoryCache setObject:@24 forKey:@"age"];
NSLog(@"age緩存在內(nèi)存:%d", [cache2.memoryCache containsObjectForKey:@"age"]);
NSLog(@"age緩存在文件:%d", [cache2.diskCache containsObjectForKey:@"age"]);

打佣幢骸:

2016-06-09 21:23:24.326 YYCache源碼分析[14512:1085375] age緩存在內(nèi)存:1
2016-06-09 21:23:24.326 YYCache源碼分析[14512:1085375] age緩存在文件:0

4.YYCache.h tips

#if __has_include(<YYCache/YYCache.h>)
#import <YYCache/YYMemoryCache.h>
#import <YYCache/YYDiskCache.h>
#import <YYCache/YYKVStorage.h>
#elif __has_include(<YYWebImage/YYCache.h>)
#import <YYWebImage/YYMemoryCache.h>
#import <YYWebImage/YYDiskCache.h>
#import <YYWebImage/YYKVStorage.h>
#else
#import "YYMemoryCache.h"
#import "YYDiskCache.h"
#import "YYKVStorage.h"
#endif

__has_include:用來檢查Frameworks是否引入某個類蟆淀,
YYWebImage已經(jīng)集成YYCache,如果導入過YYWebImage則無需重新導入YYCache

NS_ASSUME_NONNULL_BEGIN
@interface YYCache : NSObject
...
- (nullable instancetype)initWithName:(NSString *)name;
...
@end
NS_ASSUME_NONNULL_END

接口中 nullable 的是少數(shù),一般都為nonnull,為了防止寫一大堆 nonnull,F(xiàn)oundation供了一對宏NS_ASSUME_NONNULL_BEGIN澡匪、NS_ASSUME_NONNULL_END熔任,包在里面的對象默認加 nonnull 修飾符,如果是nullable的,只需要把 nullable 的指出來就行

- (instancetype)init UNAVAILABLE_ATTRIBUTE;
+ (instancetype)new UNAVAILABLE_ATTRIBUTE;

<p>
command+鼠標左鍵UNAVAILABLE_ATTRIBUTE唁情,
發(fā)現(xiàn)宏定義#define UNAVAILABLE_ATTRIBUTE __attribute__((unavailable)),
__attribute__Clang提供的一種源碼注解笋敞,方便開發(fā)者向編譯器表達某種要求,括號里是傳達某種命令.
為方便使用,一些常用屬性也被Cocoa定義成宏,
比如UNAVAILABLE_ATTRIBUTE荠瘪、NS_CLASS_AVAILABLE_IOS(9_0).
unavailable告訴編譯器該方法失效.
在封裝單例或初始化某個類前必須做一些事時,對一些方法禁用是非常不錯的選擇.
還可以給個message提示:

+ (instancetype)alloc __attribute__((unavailable("alloc方法不可用夯巷,請用initWithName:")));
- (instancetype)init __attribute__((unavailable("init方法不可用,請用initWithName:")));
+ (instancetype)new __attribute__((unavailable("new方法不可用哀墓,請用initWithName:")));
- (instancetype)copy __attribute__((unavailable("copy方法不可用趁餐,請用initWithName:")));

</p>

- (nullable instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER;

NS_DESIGNATED_INITIALIZER 這個宏并不是新面孔,可以使用它標志出像 Swift 一樣的指定構(gòu)造器和便捷構(gòu)造器篮绰。

NS_DESIGNATED_INITIALIZER關(guān)鍵字 意思是最終被指定的初始化方法后雷,在interface只能用一次而且必須以init開頭的方法。
在m文件中吠各,不管init或者其他的初始化方法都要調(diào)用上面的initWithTitle方法初始化臀突,因為我么用到了NS_DESIGNATED_INITIALIZER關(guān)鍵字,不知道明白沒贾漏?http://www.cocoachina.com/bbs/read.php?tid-282223.html



References
http://blog.sunnyxx.com/2016/05/14/clang-attributes/
http://blog.sunnyxx.com/2015/06/12/objc-new-features-in-2015/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末候学,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子纵散,更是在濱河造成了極大的恐慌梳码,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伍掀,死亡現(xiàn)場離奇詭異掰茶,居然都是意外死亡,警方通過查閱死者的電腦和手機蜜笤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門濒蒋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人把兔,你說我怎么就攤上這事沪伙∥屯纾” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵焰坪,是天一觀的道長趣倾。 經(jīng)常有香客問我,道長某饰,這世上最難降的妖魔是什么儒恋? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮黔漂,結(jié)果婚禮上诫尽,老公的妹妹穿的比我還像新娘。我一直安慰自己炬守,他們只是感情好牧嫉,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著减途,像睡著了一般酣藻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鳍置,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天辽剧,我揣著相機與錄音,去河邊找鬼税产。 笑死怕轿,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的辟拷。 我是一名探鬼主播撞羽,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼衫冻!你這毒婦竟也來了诀紊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤羽杰,失蹤者是張志新(化名)和其女友劉穎渡紫,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體考赛,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年莉测,在試婚紗的時候發(fā)現(xiàn)自己被綠了颜骤。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡捣卤,死狀恐怖忍抽,靈堂內(nèi)的尸體忽然破棺而出八孝,到底是詐尸還是另有隱情,我是刑警寧澤鸠项,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布干跛,位于F島的核電站,受9級特大地震影響祟绊,放射性物質(zhì)發(fā)生泄漏楼入。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一牧抽、第九天 我趴在偏房一處隱蔽的房頂上張望嘉熊。 院中可真熱鬧,春花似錦扬舒、人聲如沸阐肤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽孕惜。三九已至,卻和暖如春晨炕,著一層夾襖步出監(jiān)牢的瞬間衫画,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工府瞄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留碧磅,地道東北人。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓遵馆,卻偏偏與公主長得像鲸郊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子货邓,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 2016-06-14 08:11編輯:cocopeng分類:iOS開發(fā)來源:漢斯哈哈哈的簡書 34436 iOSY...
    橙娃閱讀 686評論 0 1
  • iOS 開發(fā)中總會用到各種緩存秆撮,YYCache或許是你最好的選擇。性能上有優(yōu)勢换况,用法也很簡單职辨。作者ibireme曾...
    漢斯哈哈哈閱讀 11,801評論 23 75
  • 禪與 Objective-C 編程藝術(shù) (Zen and the Art of the Objective-C C...
    GrayLand閱讀 1,607評論 1 10
  • 前言 通過閱讀別人的優(yōu)秀源碼,你會發(fā)現(xiàn)別人的開源API設計中戈二,有一些宏你是經(jīng)常忽略的舒裤,或者你不知道的。通過這些宏觉吭,...
    gitKong閱讀 5,149評論 5 41
  • 感謝主节值!神賜我美好的一天,永生的神是我的神榜聂,我的一切都在主的手中搞疗,我信的神必成全關(guān)乎我一切的事,神是愛我的须肆,主每天...
    張世超閱讀 232評論 0 0