對(duì)于NSCache的一些理解
對(duì)于有一定開發(fā)經(jīng)驗(yàn)的iOS攻城獅來說,我們在對(duì)一個(gè)APP數(shù)據(jù)做存儲(chǔ)和內(nèi)存優(yōu)化的時(shí)候,不可避免的需要對(duì)緩存做相應(yīng)的處理,而且緩存處理的優(yōu)劣,往往也是決定一個(gè)APP能否長線發(fā)展的重要因素之一,今天就來說一下經(jīng)常容易被我們忽略的一個(gè)蘋果官方提供的一套緩存機(jī)制--->NSCache
什么是NSCache?
1. NSCache蘋果提供的一套緩存機(jī)制
主要作用于內(nèi)存緩存的管理方面;
在沒有引入NSCache之前,我們要管理緩存,都是使用的NSMutableDictionary來管理,如:
// 定義下載操作緩存池
@property (nonatomic, strong) NSMutableDictionary *operationCache;
// 定義圖片緩存池
@property (nonatomic, strong) NSMutableDictionary *imageCache;
然而,使用NSMutableDictionary來管理緩存是有些不妥的, 知道多線程操作原理的開發(fā)者都明白, NSMutableDictionary在線程方面來說是不安全,這也是蘋果官方文檔明確說明了的,而如果使用的是NSCache,那就不會(huì)出現(xiàn)這些問題.所以接下來我們先看看二者的區(qū)別:
&1 NSCache和NSMutableDictionary的相同點(diǎn)與區(qū)別:
相同點(diǎn):
NSCache和NSMutableDictionary功能用法基本是相同的。
區(qū)別:
- NSCache是線程安全的售碳,NSMutableDictionary線程不安全
NSCache線程是安全的稀蟋,Mutable開發(fā)的類一般都是線程不安全的 - 當(dāng)內(nèi)存不足時(shí)NSCache會(huì)自動(dòng)釋放內(nèi)存(所以從緩存中取數(shù)據(jù)的時(shí)候總要判斷是否為空)
- NSCache可以指定緩存的限額,當(dāng)緩存超出限額自動(dòng)釋放內(nèi)存
緩存限額:
- 緩存數(shù)量
@property NSUInteger countLimit; - 緩存成本
@property NSUInteger totalCostLimit;
- 蘋果給NSCache封裝了更多的方法和屬性,比NSMutableDictionary的功能要強(qiáng)大很多
2.代碼演示:
先定義緩存池,并懶加載初始化:
#import "ViewController.h"
@interface ViewController () <NSCacheDelegate>
// 定義緩存池
@property (nonatomic, strong) NSCache *cache;
@end
@implementation ViewController
- (NSCache *)cache {
if (_cache == nil) {
_cache = [[NSCache alloc] init];
// 緩存中總共可以存儲(chǔ)多少條
_cache.countLimit = 5;
// 緩存的數(shù)據(jù)總量為多少
_cache.totalCostLimit = 1024 * 5;
}
return _cache;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//添加緩存數(shù)據(jù)
for (int i = 0; i < 10; i++) {
[self.cache setObject:[NSString stringWithFormat:@"hello %d",i] forKey:[NSString stringWithFormat:@"h%d",i]];
NSLog(@"添加 %@",[NSString stringWithFormat:@"hello %d",i]);
}
//輸出緩存中的數(shù)據(jù)
for (int i = 0; i < 10; i++) {
NSLog(@"%@",[self.cache objectForKey:[NSString stringWithFormat:@"h%d",i]]);
}
}
控制臺(tái)輸出結(jié)果為:
**通過輸出結(jié)果可以看出: **
1.當(dāng)我們使用NSCache來創(chuàng)建緩存池的時(shí)候,我們可以很靈活的設(shè)置緩存的限額,
2.當(dāng)程序中的個(gè)數(shù)超過我們的限額的時(shí)候,會(huì)先移除最先創(chuàng)建的
3.如果已經(jīng)移除了,那么當(dāng)我們輸出緩存中的數(shù)據(jù)的時(shí)候,就只剩下后面創(chuàng)建的數(shù)據(jù)了;
3. 演示NSCache的代理方法
先設(shè)置代理對(duì)象:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//設(shè)置NSCache的代理
self.cache.delegate = self;
調(diào)用代理方法: 這里我僅用一個(gè)方法來演示:
//當(dāng)緩存被移除的時(shí)候執(zhí)行
- (void)cache:(NSCache *)cache willEvictObject:(id)obj{
NSLog(@"緩存移除 %@",obj);
}
輸出結(jié)果為:

通過結(jié)果可以看出:
NSCache的功能要比NSMutableDictionary的功能要強(qiáng)大很多很多;
4.當(dāng)遇到內(nèi)存警告的時(shí)候,
代碼演示:
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
//當(dāng)收到內(nèi)存警告,清除內(nèi)存
[self.cache removeAllObjects];
//輸出緩存中的數(shù)據(jù)
for (int i = 0; i < 10; i++) {
NSLog(@"%@",[self.cache objectForKey:[NSString stringWithFormat:@"h%d",i]]);
}
}
控制臺(tái)輸出結(jié)果:

通過結(jié)果可以看出:
當(dāng)收到內(nèi)存警告之后,清除數(shù)據(jù)之后,NSCache緩存池中所有的數(shù)據(jù)都會(huì)為空!
5.當(dāng)收到內(nèi)存警告,調(diào)用removeAllObjects 之后,無法再次往緩存池中添加數(shù)據(jù)
代碼演示:
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
//當(dāng)收到內(nèi)存警告褒搔,調(diào)用removeAllObjects 之后,無法再次往緩存中添加數(shù)據(jù)
[self.cache removeAllObjects];
//輸出緩存中的數(shù)據(jù)
for (int i = 0; i < 10; i++) {
NSLog(@"%@",[self.cache objectForKey:[NSString stringWithFormat:@"h%d",i]]);
}
}
// 觸摸事件, 以便驗(yàn)證添加數(shù)據(jù)
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self.cache removeAllObjects];
//添加緩存數(shù)據(jù)
for (int i = 0; i < 10; i++) {
[self.cache setObject:[NSString stringWithFormat:@"hello %d",i] forKey:[NSString stringWithFormat:@"h%d",i]];
// NSLog(@"添加 %@",[NSString stringWithFormat:@"hello %d",i]);
}
//輸出緩存中的數(shù)據(jù)
for (int i = 0; i < 10; i++) {
NSLog(@"%@",[self.cache objectForKey:[NSString stringWithFormat:@"h%d",i]]);
}
}
控制臺(tái)輸出結(jié)果為:

通過輸出結(jié)果,我們可以看出:
當(dāng)收到內(nèi)存警告喷面,而我們又調(diào)用removeAllObjects 之后星瘾,則無法再次往緩存中添加數(shù)據(jù);
更多詳情可以查看我的Github項(xiàng)目:
https://github.com/DXSmile/NSCache-some-understanding..git