簡介緩存
1)NSCache 是蘋果官方提供的緩存類,用法與 NSMutableDictionary 的用法很類似,在 AFNetworking 和 SDWebImage 中,使用它來管理緩存。安全
2)NSCache 在系統內存很低時,會自動釋放一些對象(備註:在模擬器中內存警告時,緩存不會作清理動做)。開發中爲了確保收到內存警告時真正釋放內存,最好調用 - (void)removeAllObjects; 方法。多線程
3)NSCache 是線程安全的,在多線程操做中,不須要對 NSCache 加鎖。測試
4)NSCache 的 key 只是作強引用,不須要實現 NSCopying協議atom
屬性:spa
/** 名稱 */ @property (copy) NSString *name; /** 代理 */ @property (nullable, assign) id<NSCacheDelegate> delegate; /** 緩存空間的最大總成本,超出上限會自動回收對象,默認值是 0,表示沒有限制 */ @property NSUInteger totalCostLimit; /** 可以緩存對象的最大數量,默認值是 0,表示沒有限制 */ @property NSUInteger countLimit; /** 標識緩存是否回收廢棄的內容,默認值是 YES,表示自動回收 */ @property BOOL evictsObjectsWithDiscardedContent;
方法:線程
/** 返回與鍵值關聯的對象 */ - (nullable ObjectType)objectForKey:(KeyType)key; /** 在緩存中設置指定鍵名對應的值,與可變字典不一樣,緩存對象不會對鍵名作 copy 操做,0 成本 */ - (void)setObject:(ObjectType)obj forKey:(KeyType)key; /** 在緩存中設置指定鍵名對應的值,而且指定該鍵值對的成本。當出現內存警告時,或者超出緩存的總成本上限時,緩存會開啓一個回收過程,刪除部分元素 @param cost 成本 (cost) 用於計算記錄在緩衝中的全部對象的總成本 */ - (void)setObject:(ObjectType)obj forKey:(KeyType)key cost:(NSUInteger)g; /** 刪除緩存中,指定鍵名的對象 */ - (void)removeObjectForKey:(KeyType)key; /** 刪除緩存中全部對象 */ - (void)removeAllObjects;
委託方法:代理
/** 緩存將要刪除對象時調用,注意:不能在此方法中修改緩存!! */ - (void)cache:(NSCache *)cache willEvictObject:(id)obj;
簡單實例:code
/** * 在此提供一個例子來進行緩存使用的說明 * 需求:將字符串存入緩存,並進行查看和清理。 * 準備:在Main.storyboard中添加按鈕,分別爲添加、檢查和刪除緩存。(在此使用須要成本的方式進行測試) */
一、建立緩存對象orm
/** 緩存屬性 */ @property (nonatomic, strong) NSCache *cache; // 經過懶加載的方式建立緩存對象 - (NSCache *)cache{ if (!_cache) { _cache = [[NSCache alloc] init]; // 設置成本爲5 當存儲的數據超過總成本數,NSCache會自動回收對象 _cache.totalCostLimit = 5; // 設置代理 代理方法通常不會用到,通常是進行測試的時候使用 _cache.delegate = self; } return _cache; }
二、實現按鈕的點擊方法
// 添加緩存 - (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(@"清理緩存"); }
三、實現代理
#pragma mark - NSCacheDelegate // 即將回收對象的時候進行調用,實現代理方法以前要遵照NSCacheDelegate協議。 - (void)cache:(NSCache *)cache willEvictObject:(id)obj{ NSLog(@"回收--------%@",obj); }
四、打印說明
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)); }