一、关于yycache

开发 iOS 的老铁们对 yykit 应该非常熟悉了,不熟悉的可直接移步至:https://github.com/ibireme/YYCache,非常牛逼。

二、本文介绍

最近项目中遇到一个场景,需要指定某个 key 在存储时可指定有效期,若过期,则删除改 KEY 并 return nil,话不多说先上代码,文末讲大致的实现逻辑。
核心代码主要在YYCache.m 文件中

//
//  YYCache.m
//  YYCache <https://github.com/ibireme/YYCache>
//
//  Created by ibireme on 15/2/13.
//  Copyright (c) 2015 ibireme.
//
//  This source code is licensed under the MIT-style license found in the
//  LICENSE file in the root directory of this source tree.
//#import "YYCache.h"
#import "YYMemoryCache.h"
#import "YYDiskCache.h"//过期时间标识
static NSString * const EXPIRE_TIME = @"expire_time_";
@implementation YYCache- (instancetype) init {NSLog(@"Use \"initWithName\" or \"initWithPath\" to create YYCache instance.");return [self initWithPath:@""];
}- (instancetype)initWithName:(NSString *)name {if (name.length == 0) return nil;NSString *cacheFolder = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];NSString *path = [cacheFolder stringByAppendingPathComponent:name];return [self initWithPath:path];
}- (instancetype)initWithPath:(NSString *)path {if (path.length == 0) return nil;YYDiskCache *diskCache = [[YYDiskCache alloc] initWithPath:path];if (!diskCache) return nil;NSString *name = [path lastPathComponent];YYMemoryCache *memoryCache = [YYMemoryCache new];memoryCache.name = name;self = [super init];_name = name;_diskCache = diskCache;_memoryCache = memoryCache;return self;
}+ (instancetype)cacheWithAppId:(NSString *)appid {return [[self alloc] initWithName:appid];
}+ (instancetype)cacheWithPath:(NSString *)path {return [[self alloc] initWithPath:path];
}- (BOOL)containsObjectForKey:(NSString *)key {//判断是否过期BOOL b = [self checkKeyIsExpire:key];if (b) {return NO;}return [_memoryCache containsObjectForKey:key] || [_diskCache containsObjectForKey:key];
}- (void)containsObjectForKey:(NSString *)key withBlock:(void (^)(NSString *key, BOOL contains))block {if (!block) return;//判断是否过期BOOL b = [self checkKeyIsExpire:key];if (b) {[self removeObjectForKey:key];dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{block(key, NO);});}else{if ([_memoryCache containsObjectForKey:key]) {dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{block(key, YES);});} else  {[_diskCache containsObjectForKey:key withBlock:block];}}
}- (id<NSCoding>)objectForKey:(NSString *)key {//判断是否过期BOOL b = [self checkKeyIsExpire:key];if (b) {[self removeObjectForKey:key];return nil;}id<NSCoding> object = [_memoryCache objectForKey:key];if (!object) {object = [_diskCache objectForKey:key];if (object) {[_memoryCache setObject:object forKey:key];}}return object;
}- (void)objectForKey:(NSString *)key withBlock:(void (^)(NSString *key, id<NSCoding> object))block {if (!block) return;//判断是否过期BOOL b = [self checkKeyIsExpire:key];if (b) {[self removeObjectForKey:key];return ;}id<NSCoding> object = [_memoryCache objectForKey:key];if (object) {dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{block(key, object);});} else {[_diskCache objectForKey:key withBlock:^(NSString *key, id<NSCoding> object) {if (object && ![_memoryCache objectForKey:key]) {[_memoryCache setObject:object forKey:key];}block(key, object);}];}
}- (void)setObject:(id<NSCoding>)object forKey:(NSString *)key {[_memoryCache setObject:object forKey:key];[_diskCache setObject:object forKey:key];
}- (void)setObject:(id<NSCoding>)object forKey:(NSString *)key withBlock:(void (^)(void))block {[_memoryCache setObject:object forKey:key];[_diskCache setObject:object forKey:key withBlock:block];
}- (void)setObject:(nullable id<NSCoding>)object forKey:(NSString *)key expiretime:(int)expiretime{[_memoryCache setObject:object forKey:key];[_diskCache setObject:object forKey:key];//存储过期时间NSString *timeKey = [self getTimeKey:key];NSString *timeValue = [self getTimeValue:expiretime];[_memoryCache setObject:timeValue forKey:timeKey];[_diskCache setObject:timeValue forKey:timeKey];}- (void)setObject:(nullable id<NSCoding>)object forKey:(NSString *)key expiretime:(int)expiretime withBlock:(nullable void(^)(void))block{[_memoryCache setObject:object forKey:key];[_diskCache setObject:object forKey:key withBlock:block];//存储过期时间NSString *timeKey = [self getTimeKey:key];NSString *timeValue = [self getTimeValue:expiretime];[_memoryCache setObject:timeValue forKey:timeKey];[_diskCache setObject:timeValue forKey:timeKey withBlock:nil];
}- (void)removeObjectForKey:(NSString *)key {[_memoryCache removeObjectForKey:key];[_diskCache removeObjectForKey:key];//删除时间 KEYNSString *timeKey = [self getTimeKey:key];[_memoryCache removeObjectForKey:timeKey];[_diskCache removeObjectForKey:timeKey];
}- (void)removeObjectForKey:(NSString *)key withBlock:(void (^)(NSString *key))block {[_memoryCache removeObjectForKey:key];[_diskCache removeObjectForKey:key withBlock:block];//删除时间 KEYNSString *timeKey = [self getTimeKey:key];[_diskCache removeObjectForKey:timeKey withBlock:nil];[_diskCache removeObjectForKey:timeKey];}- (void)removeAllObjects {[_memoryCache removeAllObjects];[_diskCache removeAllObjects];
}- (void)removeAllObjectsWithBlock:(void(^)(void))block {[_memoryCache removeAllObjects];[_diskCache removeAllObjectsWithBlock:block];
}- (void)removeAllObjectsWithProgressBlock:(void(^)(int removedCount, int totalCount))progressendBlock:(void(^)(BOOL error))end {[_memoryCache removeAllObjects];[_diskCache removeAllObjectsWithProgressBlock:progress endBlock:end];}- (NSString *)description {if (_name) return [NSString stringWithFormat:@"<%@: %p> (%@)", self.class, self, _name];else return [NSString stringWithFormat:@"<%@: %p>", self.class, self];
}/// 获取当前 秒的时间戳
-(NSString *)getNowTimeTimestamp{NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0];NSTimeInterval a=[dat timeIntervalSince1970];NSString*timeString = [NSString stringWithFormat:@"%0.f", a];return timeString;
}///为 KEY 追加时间字符
-(NSString *)getTimeKey:(NSString *)key{NSString *timeKey = [NSString stringWithFormat:@"%@%@",EXPIRE_TIME,key];return timeKey;
}/// 组装时间 value
/// @param expiretime 过期时间
-(NSString *)getTimeValue:(int)expiretime {NSString *timestamp = [self getNowTimeTimestamp];NSString *timeValue = [NSString stringWithFormat:@"%@-%d",timestamp,expiretime];return timeValue;
}根据 key 反查时间 KEY
-(BOOL)checkKeyIsExpire:(NSString *)key{NSString * timeKey = [self getTimeKey:key];id<NSCoding> timeValue = [_memoryCache objectForKey:timeKey];if (!timeValue) {timeValue = [_diskCache objectForKey:timeKey];if (timeValue) {[_memoryCache setObject:timeValue forKey:timeKey];}}if(timeValue == nil){return NO;}NSString *timeStringValue = [NSString stringWithFormat:@"%@",timeValue];//分隔 “时间戳-过期时间”@try {NSArray *array = [timeStringValue componentsSeparatedByString:@"-"];NSString *expireTimeStamp = array[0];NSString *expiretime = array[1];int longExpireTimeStamp = [expireTimeStamp intValue];int intExpiretime = [expiretime intValue];int longNewTimeStamp = [[self getNowTimeTimestamp] intValue];int t = longNewTimeStamp - longExpireTimeStamp;if (t >= intExpiretime) {//删除过期的 时间 key[self removeObjectForKey:key];[self removeObjectForKey:timeKey];return YES;}} @catch (NSException *exception) {return NO;NSLog(@"%@", exception.description);}return NO;
}@end

YYCache.h 文件

//
//  YYCache.h
//  YYCache <https://github.com/ibireme/YYCache>
//
//  Created by ibireme on 15/2/13.
//  Copyright (c) 2015 ibireme.
//
//  This source code is licensed under the MIT-style license found in the
//  LICENSE file in the root directory of this source tree.
//#import <Foundation/Foundation.h>#if __has_include(<YYCache/YYCache.h>)
FOUNDATION_EXPORT double YYCacheVersionNumber;
FOUNDATION_EXPORT const unsigned char YYCacheVersionString[];
#import <YYCache/YYMemoryCache.h>
#import <YYCache/YYDiskCache.h>
#import <YYCache/YYKVStorage.h>
#elif __has_include(<YYWebImage/YYCache.h>)
#import <YYWebImage/YYMemoryCache.h>
#import <YYWebImage/YYDiskCache.h>
#import <YYWebImage/YYKVStorage.h>
#else
#import "YYMemoryCache.h"
#import "YYDiskCache.h"
#import "YYKVStorage.h"
#endifNS_ASSUME_NONNULL_BEGIN/**`YYCache` is a thread safe key-value cache.It use `YYMemoryCache` to store objects in a small and fast memory cache,and use `YYDiskCache` to persisting objects to a large and slow disk cache.See `YYMemoryCache` and `YYDiskCache` for more information.*/
@interface YYCache : NSObject/** The name of the cache, readonly. */
@property (copy, readonly) NSString *name;/** The underlying memory cache. see `YYMemoryCache` for more information.*/
@property (strong, readonly) YYMemoryCache *memoryCache;/** The underlying disk cache. see `YYDiskCache` for more information.*/
@property (strong, readonly) YYDiskCache *diskCache;/**Create a new instance with the specified name.Multiple instances with the same name will make the cache unstable.@param name  The name of the cache. It will create a dictionary with the name inthe app's caches dictionary for disk cache. Once initialized you should not read and write to this directory.@result A new cache object, or nil if an error occurs.*/
- (nullable instancetype)initWithName:(NSString *)name;/**Create a new instance with the specified path.Multiple instances with the same name will make the cache unstable.@param path  Full path of a directory in which the cache will write data.Once initialized you should not read and write to this directory.@result A new cache object, or nil if an error occurs.*/
- (nullable instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER;/**根据a appid 初始化缓存实例@param name  The name of the cache. It will create a dictionary with the name inthe app's caches dictionary for disk cache. Once initialized you should not read and write to this directory.@result A new cache object, or nil if an error occurs.*/
+ (nullable instancetype)cacheWithAppId:(NSString *)appid;/**Convenience InitializersCreate a new instance with the specified path.Multiple instances with the same name will make the cache unstable.@param path  Full path of a directory in which the cache will write data.Once initialized you should not read and write to this directory.@result A new cache object, or nil if an error occurs.*/
+ (nullable instancetype)cacheWithPath:(NSString *)path;- (instancetype)init UNAVAILABLE_ATTRIBUTE;
+ (instancetype)new UNAVAILABLE_ATTRIBUTE;#pragma mark - Access Methods
///=============================================================================
/// @name Access Methods
///=============================================================================/**Returns a boolean value that indicates whether a given key is in cache.This method may blocks the calling thread until file read finished.@param key A string identifying the value. If nil, just return NO.@return Whether the key is in cache.*/
- (BOOL)containsObjectForKey:(NSString *)key;/**Returns a boolean value with the block that indicates whether a given key is in cache.This method returns immediately and invoke the passed block in background queuewhen the operation finished.@param key   A string identifying the value. If nil, just return NO.@param block A block which will be invoked in background queue when finished.*/
- (void)containsObjectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key, BOOL contains))block;/**Returns the value associated with a given key.This method may blocks the calling thread until file read finished.@param key A string identifying the value. If nil, just return nil.@return The value associated with key, or nil if no value is associated with key.*/
- (nullable id<NSCoding>)objectForKey:(NSString *)key;/**Returns the value associated with a given key.This method returns immediately and invoke the passed block in background queuewhen the operation finished.@param key A string identifying the value. If nil, just return nil.@param block A block which will be invoked in background queue when finished.*/
- (void)objectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key, id<NSCoding> object))block;/**Sets the value of the specified key in the cache.This method may blocks the calling thread until file write finished.@param object The object to be stored in the cache. If nil, it calls `removeObjectForKey:`.@param key    The key with which to associate the value. If nil, this method has no effect.*/
- (void)setObject:(nullable id<NSCoding>)object forKey:(NSString *)key;/**Sets the value of the specified key in the cache.This method returns immediately and invoke the passed block in background queuewhen the operation finished.@param object The object to be stored in the cache. If nil, it calls `removeObjectForKey:`.@param block  A block which will be invoked in background queue when finished.*/
- (void)setObject:(nullable id<NSCoding>)object forKey:(NSString *)key withBlock:(nullable void(^)(void))block;/**Sets the value of the specified key in the cache.This method may blocks the calling thread until file write finished.@param object The object to be stored in the cache. If nil, it calls `removeObjectForKey:`.@param key    The key with which to associate the value. If nil, this method has no effect.@param expiretime 过期时间*/
- (void)setObject:(nullable id<NSCoding>)object forKey:(NSString *)key expiretime:(int)expiretime;/**Sets the value of the specified key in the cache.This method returns immediately and invoke the passed block in background queuewhen the operation finished.@param object The object to be stored in the cache. If nil, it calls `removeObjectForKey:`.@param block  A block which will be invoked in background queue when finished.@param expiretime 过期时间*/
- (void)setObject:(nullable id<NSCoding>)object forKey:(NSString *)key expiretime:(int)expiretime withBlock:(nullable void(^)(void))block;/**Removes the value of the specified key in the cache.This method may blocks the calling thread until file delete finished.@param key The key identifying the value to be removed. If nil, this method has no effect.*/
- (void)removeObjectForKey:(NSString *)key;/**Removes the value of the specified key in the cache.This method returns immediately and invoke the passed block in background queuewhen the operation finished.@param key The key identifying the value to be removed. If nil, this method has no effect.@param block  A block which will be invoked in background queue when finished.*/
- (void)removeObjectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key))block;/**Empties the cache.This method may blocks the calling thread until file delete finished.*/
- (void)removeAllObjects;/**Empties the cache.This method returns immediately and invoke the passed block in background queuewhen the operation finished.@param block  A block which will be invoked in background queue when finished.*/
- (void)removeAllObjectsWithBlock:(void(^)(void))block;/**Empties the cache with block.This method returns immediately and executes the clear operation with block in background.@warning You should not send message to this instance in these blocks.@param progress This block will be invoked during removing, pass nil to ignore.@param end      This block will be invoked at the end, pass nil to ignore.*/
- (void)removeAllObjectsWithProgressBlock:(nullable void(^)(int removedCount, int totalCount))progressendBlock:(nullable void(^)(BOOL error))end;@endNS_ASSUME_NONNULL_END

三、新增的 API 如下

/**Sets the value of the specified key in the cache.This method may blocks the calling thread until file write finished.@param object The object to be stored in the cache. If nil, it calls `removeObjectForKey:`.@param key    The key with which to associate the value. If nil, this method has no effect.@param expiretime 过期时间*/
- (void)setObject:(nullable id<NSCoding>)object forKey:(NSString *)key expiretime:(int)expiretime;/**Sets the value of the specified key in the cache.This method returns immediately and invoke the passed block in background queuewhen the operation finished.@param object The object to be stored in the cache. If nil, it calls `removeObjectForKey:`.@param block  A block which will be invoked in background queue when finished.@param expiretime 过期时间*/
- (void)setObject:(nullable id<NSCoding>)object forKey:(NSString *)key expiretime:(int)expiretime withBlock:(nullable void(^)(void))block;/**

四、实现思路

1、在存储KEY 的时候根据 KEY 存储当前创建或者更新时间
2、在取 KEY 的时候,首先获取系统当前时间并和存储时间相减,如果大于设置的过期时间则自动删除改 KEY并返回 nil。

iOS基于YYCache 改造,支持缓存 KEY 过期相关推荐

  1. 基于单例模式的多键值序列号生成器实现(支持缓存)

    之前在BlogJava上发表过这篇文章,那时没怎么做整理.想不到已经有博友把它弄到ITEye来了(虽然写得水平差,但还是希望那位博友能注明是转载的).这次稍作了整理,自己也加深下印象. 使用场景:用于 ...

  2. 基于Spring的Web缓存

    缓存的基本思想其实是以空间换时间.我们知道,IO的读写速度相对内存来说是非常比较慢的,通常一个web应用的瓶颈就出现在磁盘IO的读写上.那么,如果我们在内存中建立一个存储区,将数据缓存起来,当浏览器端 ...

  3. redis缓存失效时间设为多少_java操作Redis缓存设置过期时间的方法

    关于Redis的概念和应用本文就不再详解了,说一下怎么在java应用中设置过期时间. 在应用中我们会需要使用redis设置过期时间,比如单点登录中我们需要随机生成一个token作为key,将用户的信息 ...

  4. Spring Cache使用Redis自定义缓存key

    一.什么是Spring Cache 从spring 3.1版本开始,提供了一种透明的方式来为现有的spring 应用添加cache.在应用层面与后端存储之间,提供了一层抽象,这层抽象目的在于封装各种可 ...

  5. ios 刷新头像_想请问各位大大,iOS中新旧头像缓存的策略是什么?如微信,每次更换个人头像后,服务器怎么处理新旧头像?...

    新旧头像如何处理,需要考虑服务端和客户端两个方面. 通常大公司会将文件上传做成基础服务,跟特定的应用无关.假设这里,文件上传为服务 A, 特定的应用为服务 B,客户端为 C.这时候替换头像大致有两种做 ...

  6. EGOCache如何检测缓存时间过期

    子曰:学而不思则罔,思而不学则殆. 在上一篇文章中:EGOCache缓存框架详细讲解 提到EGOCache可以设定缓存过期时间,默认是1天.查看了一下EGOCache源码,设置默认时间: [self ...

  7. iOS开发网络篇—数据缓存

    iOS开发网络篇-数据缓存 一.关于同一个URL的多次请求 有时候,对同一个URL请求多次,返回的数据可能都是一样的,比如服务器上的某张图片,无论下载多少次,返回的数据都是一样的. 上面的情况会造成以 ...

  8. java redis 数据自过期_Java架构-Redis的内存回收策略和Key过期策略,看这篇就够了...

    Redis 作为当下最热门的 Key-Value 存储系统,在大大小小的系统中都扮演着重要的角色,不管是 session 存储还是热点数据的缓存,亦或是其他场景,我们都会使用到 Redis.在生产环境 ...

  9. 为什么基于内容的读取缓存 (CBRC) 对于 Horizon View 和 VSAN 如此重要?

    原文:http://myvirtualcloud.net/?p=5444 注明:本文内容基于 VMwareVSAN beta 版本撰写,请访问http://www.vmware.com/product ...

最新文章

  1. 【iOS】Socket/TCP 通信 发送 NSString 字符串格式数据
  2. 实例:手写 CUDA 算子,让 Pytorch 提速 20 倍
  3. 细细品味C#——Socket编程专题
  4. CF735D-Taxes【数学,数论】
  5. [转]RamDisk导致远程桌面客户端无法启动问题
  6. PDE7 wave equation: intuition
  7. 深度学习实现缺陷检测算法汇总
  8. Node2vec原理剖析,代码实现
  9. html个人主题制作,个人网页制作
  10. DX11与多线程渲染
  11. 第二章 指令:计算机的语言
  12. python安装.egg文件_芳草地-小狍子的空间_百度空间
  13. 2021-08-27-亚马逊 MWS 坑 handling time(handing time)
  14. 订单需求BOM合并 自动计算
  15. 写一个用矩形法求定积分的通用公式,分别求 sinx在0-1上积分,cosx在0-1上积分,e^x在0-1上积分
  16. Python爬取ppt工作项目模板
  17. Windows Vista 官方中文正式版(MSDN)(转载)
  18. 【Python】Python脚本命令行解析
  19. python读取word文档表格里的数据
  20. 2022年江苏专转本计算机应用基础

热门文章

  1. 【HMS Core】【FAQ】【Health Kit】运动健康服务常见错误码合集 403、401、1001、20023
  2. 华为OD机试 - 员工出勤(Python) | 机试题算法思路 【2023】
  3. pyinstall加密打包
  4. 黄仁勋台大毕典演说全文
  5. php怎么对数据库修改,php怎么修改数据库数据
  6. Medical Checkup Gym - 101986C
  7. LMD的智能手机集成e-Checkup™系统使医疗级精度个人健康监测成为现实
  8. 机房布线,上走线、下走线,那个好?
  9. 《汇编语言》王爽(第四版) 第十四章 检测点及实验14
  10. Android Studio实现内容丰富的安卓手机购物商城APP