今天來共同學習一下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));
??????????? }
}