iOS缓存策略——NSCache的简单使用
今天来共同学习一下NSCache的相关知识,有疏忽的地方,还望各位不吝赐教。
一、简介
1、NSCache是苹果官方提供的的缓存类,具体使用是和NSDictionary很相似的,在AFNetworking和SDWebImage第三方框架中被用作管理缓存。
2、NSCache在系统内存很低时会自动释放对象,但是在模拟器进行演示的时候不会释放,这一点要注意,所以最好是在内存进行警告时主动去调用方法去释放对象。
3、NSCache是线程安全的,在进行多线程操作时,不需要进行加锁。
4、NSCache的Key只是对对象进行了Strong引用,而非拷贝,相关说明会在下面的例子中进行详细解释。
二、属性和方法说明
1、属性说明
// 缓存空间的最大成本,超出上限会自动回收对象,默认值是0,表示没有限制。
@property NSUInteger totalCostLimit;
// 能够缓存对象的最大数量。默认值为0,表示没有限制。
@property NSUInteger countLimit;
// 标识缓存是否回收废弃的内容。
@property BOOL evictsObjectsWithDiscardedContent;
2、方法说明
// 通过指定的键取出在缓存中存储的数据。
- (nullable ObjectType)objectForKey:(KeyType)key;
// 在缓存中设置指定键名对应的值,成本为0。
- (void)setObject:(ObjectType)obj forKey:(KeyType)key;
// 在缓存中设置指定键名对应的值,并且指定回收成本,以便进行计算存储在缓存中对象的总成本,当出现内存警告或者超出总成本时,缓存就会进行删除部分元素的操作。
- (void)setObject:(ObjectType)obj forKey:(KeyType)key cost:(NSUInteger)g;
// 通过指定的键清除在缓存中存储的数据。
- (void)removeObjectForKey:(KeyType)key;
// 清除在缓存中存储的所有数据。
- (void)removeAllObjects;
三、简单使用
/**
* 在此提供一个例子来进行缓存使用的说明
* 需求:将字符串存入缓存,并进行查看和清理。
* 准备:在Main.storyboard中添加按钮,分别为添加、检查和删除缓存。(在此使用需要成本的方式进行测试)
*/
1、创建缓存对象
/** 缓存属性 */
@property (nonatomic, strong) NSCache *cache;
// 通过懒加载的方式创建缓存对象
- (NSCache *)cache{
if (!_cache) {
_cache = [[NSCache alloc] init];
// 设置成本为5 当存储的数据超过总成本数,NSCache会自动回收对象
_cache.totalCostLimit = 5;
// 设置代理 代理方法一般不会用到,一般是进行测试的时候使用
_cache.delegate = self;
}
return _cache;
}
2、实现按钮的点击方法
// 添加缓存
- (IBAction)addCache {
for (int i = 0 ; i < 10 ; i++) {
NSString *str = [NSString stringWithFormat:@"在这里进行了存储数据"];
// 设置成本数为1
[self.cache setObject:str forKey:@(i) cost:1];
NSLog(@"存储数据----%@",@(i));
}
}
// 检查缓存
- (IBAction)checkCache {
NSLog(@"---------------------------------------------");
for (int i = 0; i < 10 ; i++) {
NSString *str = [self.cache objectForKey:@(i)];
if (str) {
NSLog(@"取出缓存中存储的数据-----%@",@(i));
}
}
}
// 清理缓存
- (IBAction)deleteCache {
[self.cache removeAllObjects];
NSLog(@"清理缓存");
}
3、实现代理
#pragma mark - NSCacheDelegate
// 即将回收对象的时候进行调用,实现代理方法之前要遵守NSCacheDelegate协议。
- (void)cache:(NSCache *)cache willEvictObject:(id)obj{
NSLog(@"回收--------%@",obj);
}
4、打印说明
4.1 点击添加按钮的打印
存储数据----0
存储数据----1
存储数据----2
存储数据----3
存储数据----4
回收--------在这里进行了存储数据
存储数据----5
回收--------在这里进行了存储数据
存储数据----6
回收--------在这里进行了存储数据
存储数据----7
回收--------在这里进行了存储数据
存储数据----8
回收--------在这里进行了存储数据
存储数据----9
4.2 点击检查按钮的打印
---------------------------------------------
取出缓存中存储的数据-----5
取出缓存中存储的数据-----6
取出缓存中存储的数据-----7
取出缓存中存储的数据-----8
取出缓存中存储的数据-----9
4.3 打印相关的解释
在此因为进行每个字符串对象存储时,成本是1,我们设置的总成本是5,字符串对象存储了10次,总成本是10,所以在存储数据5的时候会回收数据1的字符串对象,以此类推,所以打印的结果如上所示。关于清理缓存和其他相关的操作由读者们自行打印,在此不做赘述了。
四、简介中遗漏的话
/**
* 如果把例子中的添加缓存写成如下方式,就不会存在回收的打印,在检查缓存的时候也会有10条数据。
* 解释:NSCache的Key只是对对象进行了Strong引用,而非拷贝。
* 当写在for循环外部时,所以对于字符串对象只是在内存中建立了10个强引用,而存储的真正的字符串对象只有一个(字符串对象只创建了一次),所以总成本为1。
* 当写在for循环外部时,字符串对象只是在内存中建立了10个强引用,而存储的真正的字符串对象只有十个(每次都在创建新的字符串对象),所以总成本为10。
*/
// 添加缓存
- (IBAction)addCache {
// NSCache的Key只是对对象进行了Strong引用,而非拷贝,
NSString *str = [NSString stringWithFormat:@"在这里进行了存储数据"];
for (int i = 0 ; i < 10 ; i++) {
// 设置成本数为1
[self.cache setObject:str forKey:@(i) cost:1];
NSLog(@"存储数据----%@",@(i));
}
}