緩存庫介紹:
LBCacheManager庫把數(shù)據(jù)通過文件管理(NSFileManager)類,存放在沙盒中,并運用NSCache做磁 盤上的內(nèi)存。支持存取圖片,存取數(shù)據(jù)(模型必需遵守NSCoding協(xié)議),清除全部或者單個緩存,獲得全部或者單個緩存的大小(字節(jié)數(shù)),緩存的總個數(shù)以及可以緩存的個數(shù)時間。
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface LBCacheManager : NSObject
// 默認(rèn)緩存過期時間無限,可設(shè)置默認(rèn)緩存時長(秒)
@property (nonatomic, assign) NSTimeInterval cacheTime;
// 內(nèi)存中最大保存?zhèn)€數(shù),默認(rèn)為5
@property (nonatomic, assign) NSInteger cacheLimit;
//單例
+ (LBCacheManager *)sharedManager;
//獲取所有的key
- (NSArray *)allKeys;
//判斷key是否在緩存中
- (BOOL)hasCahceForKey:(NSString *)key;
//緩存的數(shù)量
- (NSUInteger)getAllCacheCount;
//緩存的總大小
- (unsigned long long) getAllCacheSize;
//某個緩存的大小
- (unsigned long long) getSingleCacheSizeForKey:(NSString *)key;
//清除所有緩存
- (void)clearAllCache;
//清除內(nèi)存中的緩存
- (void)clearMemoryCache;
//清除某個緩存
- (void)removeCacheForKey:(NSString *)key;
/////////////////////圖片緩存/////////////////////////////////
//根據(jù)key獲得緩存圖片
- (UIImage *)readImageObjectForKey:(NSString *)key;
//根據(jù)key緩存圖片
- (void)setImage:(UIImage *)image forKey:(NSString *)key;
//根據(jù)key和時間緩存圖片
- (void)setImage:(UIImage *)image forKey:(NSString *)key withTimeInterval:(NSTimeInterval)timeoutInterval;
///////////////////數(shù)據(jù)模型緩存(模型必需遵守NSCoding協(xié)議)/////////
//根據(jù)key獲得緩存數(shù)據(jù)
- (id)readObjectForkey:(NSString *)key;
//根據(jù)key緩存數(shù)據(jù)
- (void)setObectValue:(id)value forKey:(NSString *)key;
//根據(jù)key和時間緩存數(shù)據(jù)
- (void)setObectValue:(id)value forKey:(NSString *)key withTimeInterval:(NSTimeInterval)timeoutInterval;
@end
LBCacheManager.m 文件中
#import "LBCacheManager.h"
static NSString *const kPlistName = @"LBCache.plist";
@interface LBCacheManager ()
@property (strong, nonatomic) NSMutableDictionary *cachePlistDic;
@property (strong, nonatomic) dispatch_queue_t cacheDispatch;
@property (strong, nonatomic) NSCache *memoryCahce;
@end
@implementation LBCacheManager
+ (LBCacheManager *)sharedManager{
static dispatch_once_t onceToken;
static LBCacheManager * manager = nil;
dispatch_once(&onceToken, ^{
if (manager == nil ) {
manager = [[LBCacheManager alloc]init];
}
});
return manager;
}
- (instancetype)init{
if (self = [super init]) {
//1. 創(chuàng)建線程并交換線程級別
_cacheDispatch = dispatch_queue_create("lbCacheDisptch", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t tempPatch = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_set_target_queue(tempPatch, _cacheDispatch); //交換線程級別
//2 默認(rèn)數(shù)據(jù)
_cacheTime = 0 ;
_cacheLimit = 5;
//3 添加通知
[self addNotification];
//4 內(nèi)存緩存初始化
_memoryCahce = [[NSCache alloc]init];
_memoryCahce.countLimit = _cacheLimit;
//5 初始化字典內(nèi)存
_cachePlistDic = [NSMutableDictionary dictionaryWithContentsOfFile:[self cachePathForKey:kPlistName]];
if (_cachePlistDic == nil) {
_cachePlistDic = [[NSMutableDictionary alloc]init];
}
//6 創(chuàng)建文件管理以及文件
[self creatFileManager];
}
return self;
}
-(void)setCacheLimit:(NSInteger)cacheLimit{
_cacheLimit = cacheLimit;
_memoryCahce.countLimit = cacheLimit;
}
#pragma mark - allKeys(獲取所有的key)
-(NSArray *)allKeys{
return [_cachePlistDic allKeys];
}
#pragma mark - hasCahceForKey(判斷key是否在緩存中)
- (BOOL)hasCahceForKey:(NSString *)key{
__block BOOL res = NO;
res = [[NSFileManager defaultManager]fileExistsAtPath:[self cachePathForKey:key]];
return res;
}
#pragma mark - getAllCacheCount(緩存的數(shù)量)
- (NSUInteger)getAllCacheCount{
return _cachePlistDic.count;
}
#pragma mark - getAllCacheSize(緩存的大小)
- (unsigned long long)getAllCacheSize{
unsigned long long cacheSize = 0;
for (NSString *key in [_cachePlistDic allKeys]) {
NSString *cachePath = [self cachePathForKey:key];
//attributesOfItemAtPath:方法的功能是獲取文件的大小、文件的內(nèi)容等屬性
NSDictionary *attrubis = [[NSFileManager defaultManager] attributesOfItemAtPath:cachePath error:nil];
cacheSize += [attrubis fileSize];
}
return cacheSize;
}
#pragma mark - getSingleCacheSizeForKey(某個緩存的大小)
- (unsigned long long)getSingleCacheSizeForKey:(NSString *)key{
unsigned long long cacheSize = 0;
NSFileManager *manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath:[self cachePathForKey:key]]) {
cacheSize = [[manager attributesOfItemAtPath:[self cachePathForKey:key] error:nil] fileSize];
}
return cacheSize;
}
#pragma mark -clearAllCache(清除所有緩存)
- (void)clearAllCache{
//優(yōu)化運用線程,防止阻塞主線程
dispatch_async(self.cacheDispatch, ^{
for (NSString *key in _cachePlistDic.allKeys) {
[[NSFileManager defaultManager] removeItemAtPath:[self cachePathForKey:key] error:nil];
}
[_cachePlistDic removeAllObjects];
[_cachePlistDic writeToFile:[self cachePathForKey:kPlistName] atomically:YES];
[self clearMemoryCache];
});
}
#pragma mark - clearMemoryCache(清除內(nèi)存中的緩存)
- (void)clearMemoryCache{
[_memoryCahce removeAllObjects];
}
#pragma mark - removeCacheForKey(清除某個緩存)
- (void)removeCacheForKey:(NSString *)key{
NSAssert(![key isEqualToString:kPlistName], @"對不起,主plist文件不可刪除");
dispatch_async(self.cacheDispatch, ^{
[[NSFileManager defaultManager]removeItemAtPath:[self cachePathForKey:key] error:nil
];
[_cachePlistDic removeObjectForKey:key];
[_cachePlistDic writeToFile:[self cachePathForKey:kPlistName] atomically:YES];
[_memoryCahce removeObjectForKey:key];
});
}
#pragma mark - readImageObjectForKey(根據(jù)key獲得緩存圖片)
- (UIImage *)readImageObjectForKey:(NSString *)key{
if (key) {
NSData *data= [self readObjectForkey:key];
if (data) {
return [UIImage imageWithData:data];
}
}
return nil;
}
#pragma mark - setImage:(UIImage *)image forKey:(NSString *)key(根據(jù)key緩存圖片)
- (void)setImage:(UIImage *)image forKey:(NSString *)key{
[self setImage:image forKey:key withTimeInterval:_cacheTime];
}
#pragma mark - setImage:(UIImage *)image forKey:(NSString *)key withTimeInterval:(NSTimeInterval)timeoutInterval(根據(jù)key和時間緩存圖片)
- (void)setImage:(UIImage *)image forKey:(NSString *)key withTimeInterval:(NSTimeInterval)timeoutInterval{
if (!key || !image) {
return ;
}
NSData *data = UIImagePNGRepresentation(image);
data = data ? data : UIImageJPEGRepresentation(image, 1.0f);
[self setObectValue:data forKey:key withTimeInterval:timeoutInterval];
}
#pragma mark - readObjectForkey(根據(jù)key緩存數(shù)據(jù))
-(id)readObjectForkey:(NSString *)key{
if (key) {
if ([self hasCahceForKey:key]) { //判斷是否存在
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([_cachePlistDic[key] isKindOfClass:[NSData class]]) {
NSTimeInterval now = [[NSDate date] timeIntervalSinceReferenceDate];
if ([_cachePlistDic[key] timeIntervalSinceReferenceDate] <= now) {
dispatch_async(self.cacheDispatch, ^{
[fileManager removeItemAtPath:[self cachePathForKey:key] error:nil];
[_cachePlistDic writeToFile:[self cachePathForKey:key] atomically:YES];
[_memoryCahce removeObjectForKey:key];
});
return nil;
}
}
if ([self.memoryCahce objectForKey:key]) {
return [self.memoryCahce objectForKey:key];
}
NSData *data = [NSData dataWithContentsOfFile:[self cachePathForKey:key]];
if (data) {
return [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
}
}
return nil;
}
#pragma mark - setObectValue(根據(jù)key緩存數(shù)據(jù))
- (void)setObectValue:(id)value forKey:(NSString *)key{
[self setObectValue:value forKey:key withTimeInterval:_cacheTime];
}
#pragma mark -setObectValue:(id)value forKey:(NSString *)key withTimeInterval(根據(jù)key和時間緩存數(shù)據(jù))
- (void)setObectValue:(id)value forKey:(NSString *)key withTimeInterval:(NSTimeInterval)timeoutInterval{
if (!key || !value) { //沒有key和Value返回
return ;
}
//內(nèi)存添加緩存
[self.memoryCahce setObject:value forKey:key];
[self setDataValue:[NSKeyedArchiver archivedDataWithRootObject:value] forKey:key withTimeInterVal:timeoutInterval];
}
- (void)setDataValue:(NSData *)value forKey:(NSString *)key withTimeInterVal:(NSTimeInterval )timeoutInterval{
NSAssert(![key isEqualToString:kPlistName] , @"不能保存或修改默認(rèn)的plist");
dispatch_async(self.cacheDispatch, ^{
NSLog(@"key ==%@",key);
[value writeToFile:[self cachePathForKey:key] atomically:YES];
//[NSDate distantFuture] 返回很長時間的時間值(永久)
id obj = timeoutInterval > 0 ? [NSDate dateWithTimeIntervalSinceNow:timeoutInterval] : [NSDate distantFuture];
[_cachePlistDic setObject:obj forKey:key];
[_cachePlistDic writeToFile:[self cachePathForKey:kPlistName] atomically:YES];
});
}
#pragma mark - initMethod(初始化中方法)
//MARK - 創(chuàng)建文件
- (void)creatFileManager{
// 默認(rèn)路徑
NSString *defaulPath = [self defaulPath];
//1 文件單利
NSFileManager *fileManager = [NSFileManager defaultManager];
//2 判斷是否存在文件
if ([fileManager fileExistsAtPath:defaulPath]) {
NSMutableDictionary *removeKeys = [[NSMutableDictionary alloc]init];
//timeIntervalSinceReferenceDate/以2001/01/01 GMT為基準(zhǔn)時間,返回實例保存的時間與2001/01/01 GMT的時間間隔
NSTimeInterval now = [[NSDate date] timeIntervalSinceReferenceDate];
dispatch_sync(_cacheDispatch, ^{
BOOL isChange = NO;
//遍歷字典 查看是否存在文件
for (NSString *key in _cachePlistDic.allKeys) {
//先刪除后添加
if ([_cachePlistDic[key] isKindOfClass:[NSData class]]) {
if ([_cachePlistDic[key] timeIntervalSinceReferenceDate] <= now) {
isChange = YES;
[fileManager removeItemAtPath:[self cachePathForKey:key] error:nil];
[removeKeys removeObjectForKey:key];
}
}
}
//刪除后寫入文件
if (isChange) {
_cachePlistDic = removeKeys;
[_cachePlistDic writeToFile:[self cachePathForKey:kPlistName] atomically:YES];
}
});
}else{
//沒有文件的話先去創(chuàng)建文件
[fileManager createDirectoryAtPath:defaulPath withIntermediateDirectories:YES attributes:nil error:nil];
}
}
//MARK - 添加內(nèi)存警告通知
- (void)addNotification{
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(clearMemoryCache) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
}
//MARK - 移除通知
- (void)removeNotification{
[[NSNotificationCenter defaultCenter]removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
}
//MARK- 默認(rèn)路徑
- (NSString *)defaulPath{
NSString *cachesDirectory = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
NSString *defaulPath = [[[cachesDirectory stringByAppendingPathComponent:[[NSBundle mainBundle] bundleIdentifier]]stringByAppendingPathComponent:@"LBCache"] copy];
return defaulPath;
}
//MARK -緩存路徑
- (NSString *)cachePathForKey:(NSString *)key{
return [[self defaulPath] stringByAppendingPathComponent:key].copy;
}
@end
直接復(fù)制代碼,放到類中運用就可以。有問題可以留言。