NSCache是一個(gè)繼承NSObjec的可變集合,是蘋果提供的一套緩存機(jī)制,用鍵值(key-value)對(duì)來(lái)臨時(shí)存儲(chǔ)只需要短暫存儲(chǔ)在內(nèi)存中的數(shù)據(jù),并且當(dāng)內(nèi)存空間很少的時(shí)候會(huì)可以自動(dòng)釋放一些資源。
概觀
緩存(cache)對(duì)象和其他可變集合不同的幾個(gè)方面妖滔。
-
NSCache
類包含了各種自動(dòng)銷毀策略,來(lái)保證緩存內(nèi)容沒(méi)有占用過(guò)多的系統(tǒng)內(nèi)存桶良。如果其他應(yīng)用需要內(nèi)存铛楣,這些策略會(huì)從系統(tǒng)中移除一些選項(xiàng)內(nèi)容,來(lái)減少當(dāng)前app占用的內(nèi)存空間艺普。 - 可以在不同的線程中對(duì)內(nèi)存中的緩存執(zhí)行添加簸州、移除和查詢操作,而不必自己鎖住緩存,因?yàn)槭蔷€程安全的歧譬。
- 不同于
NSMutableDictionary
對(duì)象岸浑,緩存使用的key是不需要是實(shí)現(xiàn)NSCopying協(xié)議的,NSMutableDictionary是非線程安全的瑰步,在OC中可變類型一般都是非線程安全的矢洲。 -
NSCache
可以指定緩存數(shù)量(限額)和一共可用的空間容量,當(dāng)緩存超出限額或者可用內(nèi)存容量會(huì)自動(dòng)釋放相應(yīng)內(nèi)存缩焦。
通常使用NSCache對(duì)象去臨時(shí)存儲(chǔ)那些創(chuàng)建很昂貴的過(guò)渡數(shù)據(jù)读虏。重用這些數(shù)據(jù)可以提供性能優(yōu)勢(shì)责静,因?yàn)檫@些值沒(méi)必要被重新計(jì)算。有些數(shù)據(jù)并非是關(guān)鍵數(shù)據(jù)盖桥,在內(nèi)存緊張的時(shí)候灾螃,可以被丟棄。如果丟棄揩徊,這些值將會(huì)被重新計(jì)算腰鬼。
具有子組件的對(duì)象在沒(méi)有被使用時(shí)可以被丟棄,該對(duì)象可以采用NSDiscardableContent協(xié)議塑荒,去提高緩存回收行為熄赡。默認(rèn)情況下。在緩存中的NSDiscardableContent對(duì)象丟棄的內(nèi)容會(huì)被自動(dòng)移出緩存齿税,即使這個(gè)自動(dòng)移除政策是可以修改的彼硫。如果一個(gè)NSDiscardableContent對(duì)象被放進(jìn)緩存中,那么當(dāng)該對(duì)象被移出時(shí)會(huì)調(diào)用discardContentIfPossible凌箕。
使用
以下可以使用拧篮,從多個(gè)方法介紹NSCache。
// 緩存的名稱
@property (copy) NSString *name;
設(shè)置緩存空間
// 對(duì)象緩存可持有最大的數(shù)量 陌知,默認(rèn)是0 沒(méi)有限制)他托,一旦超出限額掖肋,會(huì)自動(dòng)刪除之前添加的緩存數(shù)據(jù)
@property NSUInteger countLimit;
// 緩存中可持有的最大空間 默認(rèn)是0(沒(méi)有限制)
@property NSUInteger totalCostLimit;
管理丟棄內(nèi)容
// 是否可以自動(dòng)緩存清除可丟棄的內(nèi)容仆葡,默認(rèn)是YES
@property BOOL evictsObjectsWithDiscardedContent;
// 可以實(shí)現(xiàn)這個(gè)協(xié)議,當(dāng)類的對(duì)象有可以被銷毀不再使用的子組件志笼。這樣使用app占用更少的內(nèi)存空間沿盅。
NSDiscardableContent
設(shè)置代理
// cache的代理
@property (nullable, assign) id<NSCacheDelegate> delegate;
// 一個(gè)NSCache對(duì)象的代理,實(shí)現(xiàn)這些協(xié)議代理纫溃,去將對(duì)象從緩存中移除
NSCacheDelegate
獲取一個(gè)緩存值
// 返回給定key關(guān)聯(lián)的value值
- (nullable ObjectType)objectForKey:(KeyType)key;
添加和移除緩存值
// 根據(jù)key值設(shè)置在緩存中的value值
- (void)setObject:(ObjectType)obj forKey:(KeyType)key; // 0 cost
// 根據(jù)key值設(shè)置在緩存中的value值腰涧,并且指定關(guān)聯(lián)key-value對(duì)的成本
- (void)setObject:(ObjectType)obj forKey:(KeyType)key cost:(NSUInteger)g;
// 根據(jù)key值移除在緩存的value值
- (void)removeObjectForKey:(KeyType)key;
// 清空全部緩存,調(diào)用次方法依然可以添加新值紊浩,網(wǎng)上很多復(fù)制粘貼的博客窖铡,都說(shuō)調(diào)用次方法后不能添加,親測(cè)是可以的坊谁。
- (void)removeAllObjects;
NSCacheDelegate 方法
@protocol NSCacheDelegate <NSObject>
@optional
// 回收內(nèi)存空間使用费彼。
// cache 緩存對(duì)象。
// obj 被回收的對(duì)象口芍。
- (void)cache:(NSCache *)cache willEvictObject:(id)obj;
@end
在NSObject.h中的可以廢棄內(nèi)容箍铲。
/*********** Discardable Content ***********/
@protocol NSDiscardableContent
@required
- (BOOL)beginContentAccess;
- (void)endContentAccess;
- (void)discardContentIfPossible;
- (BOOL)isContentDiscarded;
@end
@interface NSObject (NSDiscardableContentProxy)
@property (readonly, retain) id autoContentAccessingProxy;
@end
使用
- 初始化對(duì)象
// 1. 初始化數(shù)據(jù)
- (NSCache *)mainCache{
if (!_mainCache) {
_mainCache = [[NSCache alloc] init];
_mainCache.countLimit = 300; // 限制個(gè)數(shù),默認(rèn)是0鬓椭,無(wú)限空間
_mainCache.totalCostLimit = 5*1024*1024; // 設(shè)置大小設(shè)置颠猴,默認(rèn)是0关划,無(wú)限空間
_mainCache.name = @"cache1";
_mainCache.delegate = self;
}
return _mainCache;
}
- 添加緩存
// 添加緩存
[self.mainCache setObject:data forKey:str];
- 移除。在內(nèi)存警告的時(shí)候(
didReceiveMemoryWarning
)移除緩存翘瓮。給對(duì)象發(fā)送removeAllObjects
贮折,后添加緩存setObject:forKey:
是可以的,可以再添加進(jìn)去的春畔。還有一個(gè)根據(jù)key移除對(duì)應(yīng)的值脱货。
[self.mainCache removeAllObjects];
//[self.mainCache removeObjectForKey:@"XXX"];
- 代理
在當(dāng)前對(duì)象遵守NSCacheDelegate協(xié)議。并且實(shí)現(xiàn)協(xié)議律姨。并且讓當(dāng)前對(duì)象成為代理_mainCache.delegate = self;
- (void)cache:(NSCache *)cache willEvictObject:(id)obj{
NSLog(@"%s",__func__);
}