配色: 字号:
Objective-C的缓存框架EGOCache在iOS App开发中的使用
2016-11-04 | 阅:  转:  |  分享 
  
Objective-C的缓存框架EGOCache在iOSApp开发中的使用



这篇文章主要介绍了Objective-C的缓存框架EGOCache在iOSApp开发中的使用,重点讲解了EGOCache对缓存过期时间的检测及处理,需要的朋友可以参考下



EGOCache简介



EGOCacheisasimple,thread-safekeyvaluecachestore.IthasnativesupportforNSString,UI/NSImage,andNSData,butcanstoreanythingthatimplements.Allcacheditemsexpireafterthetimeout,whichbydefault,isoneday.

翻译过来就是:EGOCache一个简单、线程安全的基于key-value的缓存框架,原生支持NSString、UI/NSImage、和NSData,也支持储存任何实现协议的类,可以设定缓存过期时间,默认是1天。



EGOCache只有一个类,EGOCache.h和EGOCache.m两个文件。用法也比较容易掌握,仔细研究一下EGOCache.h的方法,很快就可以上手。



EGOCache只提供了磁盘缓存,没有提供内存缓存。同时,也提供了清理缓存的方法:





复制代码代码如下:





-(void)clearCache;





EGOCache还提供了判断缓存是否存在的方法:



复制代码代码如下:





-(BOOL)hasCacheForKey:(NSString__nonnull)key;





通过Cocoapods直接加入项目



直接在你的项目的Podfile加入下面一行:





复制代码代码如下:





pod''EGOCache''





然后执行:



复制代码代码如下:





$podupdate





EGOCache用法



用EGOCache缓存NSString



存储:





复制代码代码如下:





NSStringsaveString=@"把我保存起来吧";

[[EGOCacheglobalCache]setString:saveStringforKey:[NSStringstringWithFormat:@"EGOImageLoader-%lu",(unsignedlong)[saveStringhash]]withTimeoutInterval:246060];





读取:



复制代码代码如下:





NSStringgetSaveString=[[EGOCacheglobalCache]stringForKey:[NSStringstringWithFormat:@"EGOImageLoader-%lu",(unsignedlong)[@"SaveString"hash]]];





是不是感觉跟NSDictionary很相似,确实,前面我们说了EGOCache是基于key-value的缓存框架。



用EGOCache缓存UIImage



存储:





复制代码代码如下:





UIImagesaveImage=[UIImageimageNamed:@"iOSDevTip"];

[[EGOCacheglobalCache]setImage:saveImageforKey:[NSStringstringWithFormat:@"EGOImageLoader-%lu",(unsignedlong)[@"SaveImage"hash]]withTimeoutInterval:246060];





读取:



复制代码代码如下:





UIImagegetSaveImage=[[EGOCacheglobalCache]imageForKey:[NSStringstringWithFormat:@"EGOImageLoader-%lu",(unsignedlong)[@"SaveImage"hash]]];





用EGOCache缓存NSData



存储:





复制代码代码如下:





NSDatasaveData=[NSDatadata];

[[EGOCacheglobalCache]setData:saveDataforKey:[NSStringstringWithFormat:@"EGOImageLoader-%lu",(unsignedlong)[@"SaveData"hash]]withTimeoutInterval:246060];





读取:



复制代码代码如下:





UIImagegetSaveData=[[EGOCacheglobalCache]dataForKey:[NSStringstringWithFormat:@"EGOImageLoader-%lu",(unsignedlong)[@"SaveData"hash]]];







EGOCache如何检测缓存时间过期

EGOCache可以设定缓存过期时间,默认是1天。查看了一下EGOCache源码,设置默认时间:





复制代码代码如下:





[selfsetDefaultwww.visa158.comTimeoutInterval:86400];

//86400=246060刚好是一天时间。





EGOCache为什么要提供设定缓存过期时间呢?或者说设定缓存过期时间有什么好处呢?我觉得最大的好处就是可以定时清除缓存。可以设置某一项的缓存时间,很方便管理缓存。



那么问题来了:

1.EGOCache是怎么检测缓存过期时间的呢?

2.检测到时间过期之后,什么时候触发删除缓存项的?



带着这两个问题,我们来继续分析。



你会怎么实现



记得在公司里,老板经常会举这样的例子:



某某同志,刚来我们公司的时候,遇到问题就知道抱怨。从来不知道去思考怎么解决,只知道把问题抛给领导。工作半年下来,成长了很多。现在碰到问题,不仅把问题抛出来,而且还提供了自己的解决方案...

类似的例子,相信大家都听过。同样,既然前面我们提出这两个问题,我们也先来思考一下,如果我们来做该怎么解决?



如果让我来写的话,我脑海里初步实现方法有几个:

1.通过定时器来轮询,每隔一段时间检测一次。

2.写一个while循环来检测。

3.每次去读取缓存项的时候,判断缓存时间有没有过期。没过期,就返回读取的缓存项;否则,返回nil。

4.当然,还有一些方法,不一一例举了。仔细想想,这些方法弊端很容易显露出来。



为了小小的缓存时间,就用定时器轮询,显然是资源浪费

跟方法1差不多。

每次读取的时候判断是否过期,如果一直不读取,app的缓存会越来越大,也不可取。

这些方法都被排除了,还有好的方法吗?继续往下看:



EGOCache是怎么实现的?



仔细查看EGOCache源码,发现在initWithCacheDirectory:方法里,每次初始化EGOCache实例对象的时,会遍历一遍plist文件中所有已存在的缓存项,拿每个缓存项的时间和当前时间作比较,缓存项过期时间早于当前时间,则删除对应缓存文件,并删除plist文件中对应key的记录。



具体实现代码如下:



读取缓存项信息





复制代码代码如下:





_cacheInfo=[[NSDictionarydictionaryWithContentsOfFile:cachePathForKey(_directory,@"EGOCache.plist")]mutableCopy];

if(!_cacheInfo){

_cacheInfo=[[NSMutableDictionaryalloc]init];

}





获取当前时间的NSTimeInterval



复制代码代码如下:





NSTimeIntervalnow=[[NSDatedate]timeIntervalSinceReferenceDate];





声明removedKeys保存过期的缓存项对应的key



复制代码代码如下:





NSMutableArrayremovedKeys=[[NSMutableArrayalloc]init];





遍历缓存项信息并判断缓存时间



复制代码代码如下:





for(NSStringkeyin_cacheInfo){

//判断缓存项过期时间是否早于当前时间

if([_cacheInfo[key]timeInterwww.hunanwang.netvalSinceReferenceDate]<=now){

//如果缓存项过期时间早于当前时间,移除缓存项

[[NSFileManagerdefaultManager]removeItemAtPath:cachePathForKey(_directory,key)error:NULL];

//把过期的缓存项对于的key保存到removedKeys里面

[removedKeysaddObject:key];

}

}





删除过期缓存项对于的key



复制代码代码如下:





[_cacheInforemoveObjectsForKeys:removedKeys];





看到这些,是不是觉得人家思路特牛叉,反正,我是觉得这个作者不简单。到这一步就解决了吗?



EGOCache还做了什么?



细心的童鞋会发现:EGOCache是个单列类,也就是说整个程序应用周期只初始化一次。





复制代码代码如下:





+(instancetype)globalCache{

staticidinstance;



staticdispatch_once_tonceToken;

dispatch_once(&onceToken,^{

instance=[[[selfclass]alloc]init];

});

returninstance;

}





每次初始化的时候去判断了缓存项是否过期,这样做非常正确。思考一个场景:



用户打开app,EGOCache被初始化,并判断了缓存项是否过期。

如果刚好有一些缓存项在EGOCache被初始化之后过期。这个时候我们依然可以读到这个缓存项。这就不对了。

继续分析EGOCache源码发现,EGOCache在读取一个缓存项的时候,先判断缓存项是否存在,然后读取缓存项(注意:是读取EGOCache初始化的时候没有过期的缓存项,并没有说现在没有过期),最后去判断读取到的缓存项跟当前时间相比是否过期.



具体实现如下:





复制代码代码如下:





-(BOOL)hasCacheForKey:(NSString)key{

//读取EGOCache初始化的时候没有过期的缓存项

NSDatedate=[selfdateForKey:key];

if(date==nil)returnNO;

//判断读取到的缓存项当前是否过期

if([datetimeIntervalSinceReferenceDate]
return[[NSFileManagerdefaultManager]fileExistsAtPath:cachePathForKey(_directory,key)];

}

-(NSDate)dateForKey:(NSString)key{

__blockNSDatedate=nil;



dispatch_sync(_frozenCacheInfoQueue,^{

date=(self.frozenCacheInfo)[key];

});



returndate;

}





EGOCache检测缓存时间过期的思路值得学习,以后遇到类似场景,完全可以借鉴。





















献花(0)
+1
(本文系白狐一梦首藏)