2016-06-14 08:11編輯:cocopeng分類:iOS開發(fā)來源:漢斯哈哈哈的簡書
34436
本文授權(quán)轉(zhuǎn)載,作者:漢斯哈哈哈(簡書)
iOS 開發(fā)中總會用到各種緩存怔球,YYCache或許是你最好的選擇。性能上有優(yōu)勢夕晓,用法也很簡單亭畜。作者ibireme曾經(jīng)對比過同類輪子:YYCache 設(shè)計思路
1.簡單架構(gòu)圖
2.YYCache.h方法分析
@interface?YYCache?:?NSObject
//?讀取當(dāng)前數(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)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)objectForKey:(NSString?*)key;
-?(void)objectForKey:(NSString?*)key?withBlock:(nullable?void(^)(NSString?*key,?id?object))block;
//?增炊汤、改--緩存對象(可緩存遵從NSCoding協(xié)議的對象),第二個法是異步執(zhí)行,異步回調(diào)
-?(void)setObject:(nullable?id)object?forKey:(NSString?*)key;
-?(void)setObject:(nullable?id)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
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)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??_Nonnull?object)?{
//?異步回調(diào)
NSLog(@"%@",?[NSThread?currentThread]);
NSLog(@"%@",?object);
}];
});
打颖兹痢:
2016-06-09?11:35:44.069?YYCache源碼分析[13546:949048]?{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]?{number?=?3,?name?=?(null)}
2016-06-09?11:35:44.386?YYCache源碼分析[13546:949052]?(
"",
"",
"",
"",
"",
"",
"",
"",
"",
""
)
//?緩存實現(xiàn)抢腐,默認(rèn)同時進行內(nèi)存緩存與文件緩存
-?(void)setObject:(id)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"]);
打咏蠼弧:
1
22016-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()
#import?#import?#import?#elif?__has_include()
#import?#import?#import?#else
#import?"YYMemoryCache.h"
#import?"YYDiskCache.h"
#import?"YYKVStorage.h"
#endif
__has_include:用來檢查Frameworks是否引入某個類氓栈,
像YYWebImage已經(jīng)集成YYCache,如果導(dǎo)入過YYWebImage則無需重新導(dǎo)入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,包在里面的對象默認(rèn)加 nonnull 修飾符醋界,如果是nullable的,只需要把 nullable 的指出來就行
1
2-?(instancetype)init?UNAVAILABLE_ATTRIBUTE;
+?(instancetype)newUNAVAILABLE_ATTRIBUTE;
command+鼠標(biāo)左鍵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:")));
本文只是簡單剖析脂新,接下來會分析YYMemoryCache實現(xiàn)原理.
References
http://blog.sunnyxx.com/2016/05/14/clang-attributes/
http://blog.sunnyxx.com/2015/06/12/objc-new-features-in-2015/