封装缓存

封装缓存,把数据通过文件管理(NSFileManager)类,存放在沙盒中,并运用NSCache做磁盘上的内存。支持存取图片,存取数据(模型必需遵守NSCoding协议),清除全部或者单个缓存,获得全部或者单个缓存的大小(字节数),缓存的总个数以及可以缓存的个数时间。

代码:

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>


@interface LBCacheManager : NSObject

// 默认缓存过期时间无限,可设置默认缓存时长(秒)
@property (nonatomic, assign) NSTimeInterval cacheTime;

// 内存中最大保存个数,默认为5
@property (nonatomic, assign) NSInteger cacheLimit;

//单例
+ (LBCacheManager *)sharedManager;

//获取所有的key
- (NSArray *)allKeys;

//判断key是否在缓存中
- (BOOL)hasCahceForKey:(NSString *)key;

//缓存的数量
- (NSUInteger)getAllCacheCount;

//缓存的总大小
- (unsigned long long) getAllCacheSize;

//某个缓存的大小
- (unsigned long long) getSingleCacheSizeForKey:(NSString *)key;

//清除所有缓存
- (void)clearAllCache;

//清除内存中的缓存
- (void)clearMemoryCache;

//清除某个缓存
- (void)removeCacheForKey:(NSString *)key;


/图片缓存/

//根据key获得缓存图片
- (UIImage *)readImageObjectForKey:(NSString *)key;

//根据key缓存图片
- (void)setImage:(UIImage *)image forKey:(NSString *)key;

//根据key和时间缓存图片
- (void)setImage:(UIImage *)image forKey:(NSString *)key withTimeInterval:(NSTimeInterval)timeoutInterval;

///数据模型缓存(模型必需遵守NSCoding协议)/

//根据key获得缓存数据
- (id)readObjectForkey:(NSString *)key;

//根据key缓存数据
- (void)setObectValue:(id)value forKey:(NSString *)key;

//根据key和时间缓存数据
- (void)setObectValue:(id)value forKey:(NSString *)key withTimeInterval:(NSTimeInterval)timeoutInterval;

@end
#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. 创建线程并交换线程级别
        _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 默认数据
        _cacheTime = 0 ;
        _cacheLimit = 5;

        //3 添加通知
        [self addNotification];

        //4 内存缓存初始化
        _memoryCahce = [[NSCache alloc]init];
        _memoryCahce.countLimit = _cacheLimit;

        //5 初始化字典内存
        _cachePlistDic = [NSMutableDictionary dictionaryWithContentsOfFile:[self cachePathForKey:kPlistName]];
        if (_cachePlistDic == nil) {
            _cachePlistDic = [[NSMutableDictionary alloc]init];
        }

        //6 创建文件管理以及文件
        [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(缓存的数量)
- (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:方法的功能是获取文件的大小、文件的内容等属性
        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{
    //优化运用线程,防止阻塞主线程
    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(清除内存中的缓存)
- (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(根据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(根据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(根据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(根据key缓存数据)
-(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(根据key缓存数据)
- (void)setObectValue:(id)value forKey:(NSString *)key{

    [self setObectValue:value forKey:key withTimeInterval:_cacheTime];
}

#pragma mark -setObectValue:(id)value forKey:(NSString *)key withTimeInterval(根据key和时间缓存数据)
- (void)setObectValue:(id)value forKey:(NSString *)key withTimeInterval:(NSTimeInterval)timeoutInterval{

    if (!key || !value) { //没有key和Value返回
        return ;
    }

    //内存添加缓存
    [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] , @"不能保存或修改默认的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 - 创建文件
- (void)creatFileManager{

    // 默认路径
    NSString *defaulPath = [self defaulPath];

    //1 文件单利
     NSFileManager *fileManager = [NSFileManager defaultManager];

    //2 判断是否存在文件
    if ([fileManager fileExistsAtPath:defaulPath]) {
        NSMutableDictionary *removeKeys = [[NSMutableDictionary alloc]init];
        //timeIntervalSinceReferenceDate/以2001/01/01 GMT为基准时间,返回实例保存的时间与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{

       //没有文件的话先去创建文件
        [fileManager createDirectoryAtPath:defaulPath withIntermediateDirectories:YES attributes:nil error:nil];

    }
}


//MARK - 添加内存警告通知
- (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- 默认路径
- (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

直接复制代码,放到类中运用就可以。有问题可以留言。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值