iOS 开发中总会用到各种缓存,YYCache或许是你最好的选择。性能上有优势,用法也很简单。作者ibireme曾经对比过同类轮子:http://blog.ibireme.com/2015/10/26/yycache/

1.简单架构图

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<NSCoding>)objectForKey:(NSString *)key;

- (void)objectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key, id<NSCoding> object))block;

// 增、改--缓存对象(可缓存遵从NSCoding协议的对象),第二个法是异步执行,异步回调

- (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

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.缓存数组

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<NSCoding>  _Nonnull object) {

// 异步回调

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>"

)

// 缓存实现,默认同时进行内存缓存与文件缓存

- (void)setObject:(id<NSCoding>)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(<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已经集成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/

YYCache 源码分析(一)的更多相关文章

  1. YYCache 源码分析(二)

    本文分析YYMemoryCache实现原理: YYMemoryCache是内存缓存,所以存取速度非常快,主要用到两种数据结构的LRU淘汰算法 1.LRU Cache的容量是有限的,当Cache的空间都 ...

  2. iOS常用框架源码分析

    SDWebImage NSCache 类似可变字典,线程安全,使用可变字典自定义实现缓存时需要考虑加锁和释放锁 在内存不足时NSCache会自动释放存储的对象,不需要手动干预 NSCache的key不 ...

  3. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

  4. HashMap与TreeMap源码分析

    1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...

  5. nginx源码分析之网络初始化

    nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...

  6. zookeeper源码分析之五服务端(集群leader)处理请求流程

    leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...

  7. zookeeper源码分析之四服务端(单机)处理请求流程

    上文: zookeeper源码分析之一服务端启动过程 中,我们介绍了zookeeper服务器的启动过程,其中单机是ZookeeperServer启动,集群使用QuorumPeer启动,那么这次我们分析 ...

  8. zookeeper源码分析之三客户端发送请求流程

    znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...

  9. java使用websocket,并且获取HttpSession,源码分析

    转载请在页首注明作者与出处 http://www.cnblogs.com/zhuxiaojie/p/6238826.html 一:本文使用范围 此文不仅仅局限于spring boot,普通的sprin ...

随机推荐

  1. impress.js学习总结

    impress.js是一个很有趣的用来替代PPT的展示用的js工具,它的灵感来自prezi 如果你要学习使用它,这里有很好的演示模板 使用它的第一步,下载 impress.js,引入到你的代码里,并执 ...

  2. JavaScript中document.cookie

    “某些 Web 站点在您的硬盘上用很小的文本文件存储了一些信息,这些文件就称为 Cookie.”—— MSIE 帮助.一般来说,Cookies 是 CGI 或类似,比 HTML 高级的文件.程序等创建 ...

  3. jQuery运维开发之第十七天

    JQuery 学习参考网址http://jquery.cuishifeng.cn/ python中叫模块,在DOM/BOM/Javascript中叫类库 现在的JQ版本有:1.x 2.x 3.x 建议 ...

  4. KVO初探

    一,概述 KVO,即:Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知.简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应 ...

  5. RunLoop-b

    RunLoop 是 iOS 和 OSX 开发中非常基础的一个概念,这篇文章将从 CFRunLoop 的源码入手,介绍 RunLoop 的概念以及底层实现原理.之后会介绍一下在 iOS 中,苹果是如何利 ...

  6. 基于 SWTBot 进行 Eclipse GUI 自动化测试

    背景简介 在软件开发领域,持续集成和部署对于软件测试自动化提出了越来越高的要求,基于 Eclipse 应用在这一需求中仍然占据重要的组成部分.目前主流的测试自动化工具主要以录制回放的功能为主,辅助以脚 ...

  7. mysql安装2

    linux下安装mysql-5.1.51.tar.gz (2010-10-27 10:59:26) 转载▼ 标签: mysql 数据库 tar.gz安装 杂谈 分类: Mysql数据库 MySQL h ...

  8. super返回不过来

    class Fruit {     String color = "未确定颜色";     //定义一个方法,该方法返回调用该方法的实例     public Fruit getT ...

  9. FFT(快速傅里叶变换):UVAoj 12298 - Super Poker II

    题目:就是现在有一堆扑克里面的牌有无数张, 每种合数的牌有4中不同花色各一张(0, 1都不是合数), 没有质数或者大小是0或者1的牌现在这堆牌中缺失了其中的 c 张牌, 告诉你a, b, c接下来c张 ...

  10. SQL时间格式化

    1 取值后格式化 {:d}小型:如2005 {:D}大型:如2005年5月6日 {:f}完整型 2 当前时间获取 DateTime.Now.ToShortDateString 3 取值中格式化SQL ...