仅仅是自己的理解,如有错误的地方,请指正
高山仰止,景行行止
YYMemoryCache
该类主要处理将数据存放在内存中,主要有四个方面,使用CFMutableDictionaryRef
来实现数据的实际存储;使用OSSpinLockLock
来保证线程的安全;使用_YYLinkedMapNode
和_YYLinkedMap
来组织数据的存储结构;使用YYMemoryCache
来组织对数据的各种操作。
1、CFMutableDictionaryRef
想先说一点Core Foundation 框架,他是一组C语言的接口,为应用程序提供基本的数据管理和服务功能,他和Foundation框架为相同的功能提供接口,只不过Foundation框架提供的是Objective-C的接口。
/*!
@typedef CFDictionaryRef
This is the type of a reference to immutable CFDictionarys.
*/
typedef const struct CF_BRIDGED_TYPE(NSDictionary) __CFDictionary * CFDictionaryRef;
初始化一个CFMutableDictionaryRef
的实例,
CFMutableDictionaryRef _dic = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
添加数据,看官方API可以发现,添加数据其实有两个方法
CF_EXPORT
void CFDictionarySetValue(CFMutableDictionaryRef theDict, const void *key, const void *value);
和
CF_EXPORT
void CFDictionaryAddValue(CFMutableDictionaryRef theDict, const void *key, const void *value);
看区别:
- CFDictionarySetValue : If a key which matches this key is already present in the dictionary, only the value is changed ("add if absent, replace if present"). If no key matches the given key, the key-value pair is added to the .(如果key存在,则使用新的value替换原来的value,反之,则添加新的key-value)
- CFDictionaryAddValue :If key which matches this key is already present in the dictionary, function does nothing ("add if absent").(如果key存在,不做任何操作,反之,添加新的key-value)
删除指定的key
CF_EXPORT
void CFDictionaryRemoveValue(CFMutableDictionaryRef theDict, const void *key);
很容易理解的移除方式 If a key matches this key is present in the dictionary, the key-value is removed from the dictionary, otherwise this function does ("remove if present").
获取当前所有存储的key-value 的个数
CF_EXPORT
CFIndex CFDictionaryGetCount(CFDictionaryRef theDict);
判定当前的key是否存在
CF_EXPORT
Boolean CFDictionaryContainsKey(CFDictionaryRef theDict, const void *key);
获取指定key的value
CF_EXPORT
const void *CFDictionaryGetValue(CFDictionaryRef theDict, const void *key);
如果不存在该key,返回为空。
2、OSSpinLockLock
再说这个之前先了解几种加锁的方式,并测试一下他们的效率
NSInteger count = 100000;
double startTime,endTime;
NSLock *lock = [[NSLock alloc]init];
startTime = CFAbsoluteTimeGetCurrent();
for (NSInteger i = 0; i < count; i++) {
[lock lock];
[lock unlock];
}
endTime = CFAbsoluteTimeGetCurrent();
NSLog(@"NSLock = %f",endTime - startTime);
//引入库#import
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
startTime = CFAbsoluteTimeGetCurrent();
for (NSInteger i = 0; i < count; i++) {
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
}
endTime = CFAbsoluteTimeGetCurrent();
NSLog(@"pthread_mutex_t = %f",endTime - startTime);
//引入库#import
OSSpinLock spinLock = OS_SPINLOCK_INIT;
startTime = CFAbsoluteTimeGetCurrent();
for (NSInteger i = 0; i < count; i++) {
OSSpinLockLock(&spinLock);
OSSpinLockUnlock(&spinLock);
}
endTime = CFAbsoluteTimeGetCurrent();
NSLog(@"OSSpinLock = %f",endTime - startTime);
id obj = [[NSObject alloc]init];
startTime = CFAbsoluteTimeGetCurrent();
for (NSInteger i = 0; i < count; i++) {
@synchronized(obj) {
}
}
endTime = CFAbsoluteTimeGetCurrent();
NSLog(@"@synchronized = %f",endTime - startTime);
看一下打印值:
2016-01-17 10:35:06.793 YYCacheStudy[4751:442986] NSLock = 0.003598
2016-01-17 10:35:06.796 YYCacheStudy[4751:442986] pthread_mutex_t = 0.002747
2016-01-17 10:35:06.797 YYCacheStudy[4751:442986] OSSpinLock = 0.001237
2016-01-17 10:35:06.811 YYCacheStudy[4751:442986] @synchronized = 0.013879
但是在新版iOS中不能保证安全,看大神的博客《不再安全的 OSSpinLock》
其他的数据结构组成,就是简单的链表格式,不多说,还有各种外层封装,就是针对链表的操作,都是基础知识,就不写了。
YYKVStorage
上述的YYMemoryCache将数据写到内存里,一旦程序程序关闭或者达到内存警告,则数据就会消息。该类主要写了两种将数据写到本地的方法,实现了离线缓存。两种方式,一种是利用数据库SQLite,另一种采取的是写文件的方式。至于数据库,由于之前一直使用FMDB,导致对sqlite的使用并不熟,正好就这个机会学习一下。