1. 程式人生 > >iOS快取策略之NSCache的簡單使用

iOS快取策略之NSCache的簡單使用

NSCache是一個繼承NSObjec的可變集合,是蘋果提供的一套快取機制,用鍵值(key-value)對來臨時儲存只需要短暫儲存在記憶體中的資料,並且當記憶體空間很少的時候會可以自動釋放一些資源。

概觀

快取(cache)物件和其他可變集合不同的幾個方面。

  • NSCache類包含了各種自動銷燬策略,來保證快取內容沒有佔用過多的系統記憶體。如果其他應用需要記憶體,這些策略會從系統中移除一些選項內容,來減少當前app佔用的記憶體空間。
  • 可以在不同的執行緒中對記憶體中的快取執行新增、移除和查詢操作,而不必自己鎖住快取,因為是執行緒安全的。
  • 不同於NSMutableDictionary
    物件,快取使用的key是不需要是實現NSCopying協議的,NSMutableDictionary是非執行緒安全的,在OC中可變型別一般都是非執行緒安全的。
  • NSCache可以指定快取數量(限額)和一共可用的空間容量,當快取超出限額或者可用記憶體容量會自動釋放相應記憶體。

通常使用NSCache物件去臨時儲存那些建立很昂貴的過渡資料。重用這些資料可以提供效能優勢,因為這些值沒必要被重新計算。有些資料並非是關鍵資料,在記憶體緊張的時候,可以被丟棄。如果丟棄,這些值將會被重新計算。

具有子元件的物件在沒有被使用時可以被丟棄,該物件可以採用NSDiscardableContent協議,去提高快取回收行為。預設情況下。在快取中的NSDiscardableContent物件丟棄的內容會被自動移出快取,即使這個自動移除政策是可以修改的。如果一個NSDiscardableContent物件被放進快取中,那麼當該物件被移出時會呼叫discardContentIfPossible。

使用

以下可以使用,從多個方法介紹NSCache。

// 快取的名稱
@property (copy) NSString *name;

設定快取空間

// 物件快取可持有最大的數量 ,預設是0 沒有限制),一旦超出限額,會自動刪除之前新增的快取資料
@property NSUInteger countLimit;
// 快取中可持有的最大空間 預設是0(沒有限制)
@property NSUInteger totalCostLimit;

管理丟棄內容

// 是否可以自動快取清除可丟棄的內容,預設是YES
@property BOOL evictsObjectsWithDiscardedContent;
// 可以實現這個協議,當類的物件有可以被銷燬不再使用的子元件。這樣使用app佔用更少的記憶體空間。
NSDiscardableContent

設定代理

// cache的代理
@property (nullable, assign) id<NSCacheDelegate> delegate;
// 一個NSCache物件的代理,實現這些協議代理,去將物件從快取中移除
NSCacheDelegate

獲取一個快取值

// 返回給定key關聯的value值
- (nullable ObjectType)objectForKey:(KeyType)key;

新增和移除快取值

// 根據key值設定在快取中的value值
- (void)setObject:(ObjectType)obj forKey:(KeyType)key; // 0 cost
// 根據key值設定在快取中的value值,並且指定關聯key-value對的成本
- (void)setObject:(ObjectType)obj forKey:(KeyType)key cost:(NSUInteger)g;
// 根據key值移除在快取的value值
- (void)removeObjectForKey:(KeyType)key;
// 清空全部快取,呼叫次方法依然可以新增新值,網上很多很多複製貼上的部落格,都說呼叫次方法後不能新增,親測是可以的。
- (void)removeAllObjects;

NSCacheDelegate 方法

@protocol NSCacheDelegate <NSObject>
@optional
// 回收記憶體空間使用。
// cache 快取物件。
// obj 被回收的物件。
- (void)cache:(NSCache *)cache willEvictObject:(id)obj;
@end

在NSObject.h中的可以廢棄內容。

/***********    Discardable Content     ***********/

@protocol NSDiscardableContent
@required
- (BOOL)beginContentAccess;
- (void)endContentAccess;
- (void)discardContentIfPossible;
- (BOOL)isContentDiscarded;
@end

@interface NSObject (NSDiscardableContentProxy)
@property (readonly, retain) id autoContentAccessingProxy;
@end

使用

  1. 初始化物件
// 1. 初始化資料
- (NSCache *)mainCache{
    if (!_mainCache) {
        _mainCache = [[NSCache alloc] init];
        _mainCache.countLimit = 300; // 限制個數,預設是0,無限空間
        _mainCache.totalCostLimit = 5*1024*1024; // 設定大小設定,預設是0,無限空間
        _mainCache.name = @"cache1";
        _mainCache.delegate = self;
    }
    return _mainCache;
}
  1. 新增快取
// 新增快取
 [self.mainCache setObject:data forKey:str];
  1. 移除。在記憶體警告的時候(didReceiveMemoryWarning)移除快取。給物件傳送removeAllObjects,後新增快取setObject:forKey:是可以的,可以再新增進去的。還有一個根據key移除對應的值。
[self.mainCache removeAllObjects];
//[self.mainCache removeObjectForKey:@"XXX"];
  1. 代理
    在當前物件遵守NSCacheDelegate協議。並且實現協議。並且讓當前物件成為代理_mainCache.delegate = self;
- (void)cache:(NSCache *)cache willEvictObject:(id)obj{
    NSLog(@"%s",__func__);
}

推薦