T YYCache源码分析(一) - CocoaChina_让移动开发更简单

首页 >iOS开发

YYCache源码分析(一)

2016-06-14 08:11 编辑: cocopeng 分类:iOS开发 来源:汉斯哈哈哈的简书

img (121).jpg

本文授权转载,作者:汉斯哈哈哈(简书)

iOS 开发中总会用到各种缓存,YYCache或许是你最好的选择。性能上有优势,用法也很简单。作者ibireme曾经对比过同类轮子:YYCache 设计思路

1.简单架构图

295346-c7ea0fff151e74cd.png

2.YYCache.h方法分析

@interface YYCache : NSObject
// 读取当前数据库名称
@property (copy, readonly) NSString *name;
// memoryCache内存缓存,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判断是否缓存了某个东西,第二个法是异步执行,异步回调
- (BOOL)containsObjectForKey:(NSString *)key;
- (void)containsObjectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key, BOOL contains))block;
// 读--通过key读取缓存,第二个法是异步执行,异步回调
- (nullable id)objectForKey:(NSString *)key;
- (void)objectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key, id object))block;
// 增、改--缓存对象(可缓存遵从NSCoding协议的对象),第二个法是异步执行,异步回调
- (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.缓存数组
NSMutableArray *array = @[].mutableCopy;
for (NSInteger i = 0; i < 10; i ++) {
[array addObject:model];
}
// 异步缓存
[cache setObject:array forKey:@"user" withBlock:^{
// 异步回调
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) {
// 异步回调
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] (
"",
"",
"",
"",
"",
"",
"",
"",
"",
""
)
// 缓存实现,默认同时进行内存缓存与文件缓存
- (void)setObject:(id)object forKey:(NSString *)key {
[_memoryCache setObject:object forKey:key];
[_diskCache setObject:object forKey:key];
}
// 如果只想内存缓存,可以直接调用`memoryCache`对象
YYCache *cache2 = [YYCache cacheWithName:@"mydb"];
[cache2.memoryCache setObject:@24 forKey:@"age"];
NSLog(@"age缓存在内存:%d", [cache2.memoryCache containsObjectForKey:@"age"]);
NSLog(@"age缓存在文件:%d", [cache2.diskCache containsObjectForKey:@"age"]);

打印:

2016-06-09 21:23:24.326 YYCache源码分析[14512:1085375] age缓存在内存: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已经集成YYCache,如果导入过YYWebImage则无需重新导入YYCache

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

接口中 nullable 的是少数,一般都为nonnull,为了防止写一大堆 nonnull,Foundation供了一对宏NS_ASSUME_NONNULL_BEGIN、NS_ASSUME_NONNULL_END,包在里面的对象默认加 nonnull 修饰符,如果是nullable的,只需要把 nullable 的指出来就行

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

command+鼠标左键UNAVAILABLE_ATTRIBUTE,

发现宏定义#define UNAVAILABLE_ATTRIBUTE __attribute__((unavailable)),

__attribute__是Clang提供的一种源码注解,方便开发者向编译器表达某种要求,括号里是传达某种命令.

为方便使用,一些常用属性也被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实现原理.

References

http://blog.sunnyxx.com/2016/05/14/clang-attributes/

http://blog.sunnyxx.com/2015/06/12/objc-new-features-in-2015/

搜索CocoaChina微信公众号:CocoaChina
微信扫一扫
订阅每日移动开发及APP推广热点资讯
公众号:
CocoaChina
我要投稿   收藏文章
上一篇:App启动加载广告页面思路
下一篇:YYCache源码分析(二)
我来说两句
发表评论
您还没有登录!请登录注册
所有评论(0

综合评论

相关帖子

sina weixin mail 回到顶部