YYCache(二)
代码测验:
初始化YYCache
实例:
#import <YYCache/YYCache.h>
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) YYCache *contactsCache;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.contactsCache = [YYCache cacheWithName:@"Contacts”];
}
增加一个通讯录模型:
@interface ContactsModel : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *phoneNumber;
@end
增加10
条数据:
for (int i = 0; i < 10; i ++) {
ContactsModel *model = [ContactsModel new];
model.name = [NSString stringWithFormat:@"张%d",i];
model.phoneNumber = [NSString stringWithFormat:@"1588889999%d",i];
[self.contactsCache setObject:model forKey:
[NSString stringWithFormat:@"kContacts_%d",i]];
}
提示Sending 'ContactsModel *__strong' to parameter of incompatible type 'id<NSCoding> _Nullable
:
给ContactsModel
增加<NSCoding>
协议:
@interface ContactsModel : NSObject<NSCoding>
//通讯类内部的两个特点变量别离转码
- (void)encodeWithCoder:(nonnull NSCoder *)coder {
[coder encodeObject:_name forKey:@"name"];
[coder encodeObject:_phoneNumber forKey:@"phoneNumber"];
}
//别离把两个特点变量依据关键字进行逆转码,最后返回一个Contacts类的对象
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)coder {
if (self = [super init]) {
if (coder) {
_name = [coder decodeObjectOfClass:[NSString class]
forKey:@"name"];
_phoneNumber = [coder decodeObjectOfClass:[NSString class]
forKey:@"phoneNumber"];
}
}
return self;
}
提示消失,用循环把值取出来:
for (int i = 0; i < 10; i++) {
ContactsModel *model = (ContactsModel *)[self.contactsCache
objectForKey:[NSString stringWithFormat:@"kContacts_%d",i]];
NSLog(@"name = %@ phoneNumber = %@",model.name, model.phoneNumber);
}
运转打印:
YYCacheDemo[3304:73220] name = 张0 phoneNumber = 15888899990
YYCacheDemo[3304:73220] name = 张1 phoneNumber = 15888899991
YYCacheDemo[3304:73220] name = 张2 phoneNumber = 15888899992
YYCacheDemo[3304:73220] name = 张3 phoneNumber = 15888899993
YYCacheDemo[3304:73220] name = 张4 phoneNumber = 15888899994
YYCacheDemo[3304:73220] name = 张5 phoneNumber = 15888899995
YYCacheDemo[3304:73220] name = 张6 phoneNumber = 15888899996
YYCacheDemo[3304:73220] name = 张7 phoneNumber = 15888899997
YYCacheDemo[3304:73220] name = 张8 phoneNumber = 15888899998
YYCacheDemo[3304:73220] name = 张9 phoneNumber = 15888899999
打印self.contactsCache.memoryCache和self.contactsCache.diskCache,发现数据一样
主要功能:
一、增加约束
二、数据修剪
YYMemoryCache: YYDiskCach:
测验给内存增加数量约束:
self.contactsCache.memoryCache.countLimit = 5;
YYCacheDemo[4272:102918] name = (null) phoneNumber = (null)
YYCacheDemo[4272:102918] name = (null) phoneNumber = (null)
YYCacheDemo[4272:102918] name = (null) phoneNumber = (null)
YYCacheDemo[4272:102918] name = (null) phoneNumber = (null)
YYCacheDemo[4272:102918] name = (null) phoneNumber = (null)
YYCacheDemo[4272:102918] name = 张5 phoneNumber = 15888899995
YYCacheDemo[4272:102918] name = 张6 phoneNumber = 15888899996
YYCacheDemo[4272:102918] name = 张7 phoneNumber = 15888899997
YYCacheDemo[4272:102918] name = 张8 phoneNumber = 15888899998
YYCacheDemo[4272:102918] name = 张9 phoneNumber = 15888899999
发现前面的
5
个数据都被移除了
修剪最大个数为8
个:
[self.contactsCache.memoryCache trimToCount:8];
运转:
YYCacheDemo[4461:108978] name = (null) phoneNumber = (null)
YYCacheDemo[4461:108978] name = (null) phoneNumber = (null)
YYCacheDemo[4461:108978] name = 张2 phoneNumber = 15888899992
YYCacheDemo[4461:108978] name = 张3 phoneNumber = 15888899993
YYCacheDemo[4461:108978] name = 张4 phoneNumber = 15888899994
YYCacheDemo[4461:108978] name = 张5 phoneNumber = 15888899995
YYCacheDemo[4461:108978] name = 张6 phoneNumber = 15888899996
YYCacheDemo[4461:108978] name = 张7 phoneNumber = 15888899997
YYCacheDemo[4461:108978] name = 张8 phoneNumber = 15888899998
YYCacheDemo[4461:108978] name = 张9 phoneNumber = 15888899999
清空所有缓存:
[self.contactsCache removeAllObjects];
内存缓存:
YYCacheDemo[6819:162854] memory name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] memory name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] memory name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] memory name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] memory name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] memory name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] memory name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] memory name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] memory name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] memory name = (null) phoneNumber = (null)
磁盘缓存:
YYCacheDemo[6819:162854] disk name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] disk name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] disk name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] disk name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] disk name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] disk name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] disk name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] disk name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] disk name = (null) phoneNumber = (null)
YYCacheDemo[6819:162854] disk name = (null) phoneNumber = (null)
源码:
YYMemoryCache
的初始化:
- (instancetype)init {
self = super.init;
pthread_mutex_init(&_lock, NULL);
_lru = [_YYLinkedMap new];
_queue = dispatch_queue_create("com.ibireme.cache.memory", DISPATCH_QUEUE_SERIAL);
_countLimit = NSUIntegerMax;
_costLimit = NSUIntegerMax;
_ageLimit = DBL_MAX;
_autoTrimInterval = 5.0;
_shouldRemoveAllObjectsOnMemoryWarning = YES;
_shouldRemoveAllObjectsWhenEnteringBackground = YES;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appDidReceiveMemoryWarningNotification) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appDidEnterBackgroundNotification) name:UIApplicationDidEnterBackgroundNotification object:nil];
[self _trimRecursively];
return self;
}
一个_YYLinkedMap
的实例,检查_YYLinkedMap
:
@interface _YYLinkedMap : NSObject {
@package
CFMutableDictionaryRef _dic; // do not set object directly
NSUInteger _totalCost;
NSUInteger _totalCount;
_YYLinkedMapNode *_head; // MRU, do not change it directly
_YYLinkedMapNode *_tail; // LRU, do not change it directly
BOOL _releaseOnMainThread;
BOOL _releaseAsynchronously;
}
发现_YYLinkedMap
是一个双向链表,有两个_YYLinkedMapNode
类型节点,还有一个CFMutableDictionaryRef
的字典_dic
,_dic
是真正存放数据的当地。
递归修剪:
- (void)_trimRecursively {
__weak typeof(self) _self = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_autoTrimInterval * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
__strong typeof(_self) self = _self;
if (!self) return;
[self _trimInBackground];
[self _trimRecursively];
});
}
- (void)_trimInBackground {
dispatch_async(_queue, ^{
[self _trimToCost:self->_costLimit];
[self _trimToCount:self->_countLimit];
[self _trimToAge:self->_ageLimit];
});
}
每隔
_autoTrimInterval
秒就自动调用修整内存数据,_autoTrimInterval
默许是5
秒。
增加数据:
- (void)setObject:(id)object forKey:(id)key withCost:(NSUInteger)cost {
….
_YYLinkedMapNode *node = CFDictionaryGetValue(_lru->_dic, (__bridge const void *)(key));
NSTimeInterval now = CACurrentMediaTime();
if (node) {
_lru->_totalCost -= node->_cost;
_lru->_totalCost += cost;
node->_cost = cost;
node->_time = now;
node->_value = object;
[_lru bringNodeToHead:node];
} else {
node = [_YYLinkedMapNode new];
node->_cost = cost;
node->_time = now;
node->_key = key;
node->_value = object;
[_lru insertNodeAtHead:node];
}
…
pthread_mutex_unlock(&_lock);
}
由于_lru = [_YYLinkedMap new];
,能够看到就是操作_YYLinkedMap
双链表,使用的是pthread_mutex
锁。