緩存庫 -- LBCacheManager

緩存庫介紹:

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ù)制代碼,放到類中運用就可以。有問題可以留言。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 需要原文的可以留下郵箱我給你發(fā),這里的文章少了很多圖,懶得網(wǎng)上粘啦 1數(shù)據(jù)庫基礎(chǔ) 1.1數(shù)據(jù)庫定義 1)數(shù)據(jù)庫(D...
    極簡純粹_閱讀 7,889評論 0 46
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,017評論 4 61
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,716評論 25 709
  • 王繼曾在隋朝做官,但是郁郁不得志,遂托病回家。后來隋朝亡了,到了唐朝,又做了唐朝的官。到了李世民做皇帝的時候,王繼...
    不語語焉閱讀 1,951評論 4 2
  • 時間沒過多久,若楓從外面打球回來,看到妍梔在班里認(rèn)得哥哥坐在他的座位上,和妍梔說著什么,恰好妍梔的哥哥那幾天和若楓...
    七月無傷閱讀 195評論 0 0

友情鏈接更多精彩內(nèi)容