NSCache原理(有名なオープンフレームSDWebImageは、NSCacheを使用して実現されるキャッシュ)

4854 ワード

NSCacheはセットに似たコンテナであり、キャッシュである.それはkey-valueペアを記憶しています.この点はNSDictionary類に似ています.私たちは通常、キャッシュを使用して、短い時間で使用しますが、高価なオブジェクトを作成します.これらのオブジェクトを再利用して性能を最適化できます.その値は再計算を必要としないからです.一方、これらのオブジェクトはプログラムにとって重要ではなく、メモリが緊張している時に破棄されます.オブジェクトが破棄された場合は、次回の使用時に再計算が必要です.
key-valueペアがキャッシュにあるとき、キャッシュはその強い参照を維持する.NSCacheに記憶されている汎用データタイプは、一般にNSDiscable Controntプロトコルを実装したオブジェクトである.このようなオブジェクトをキャッシュに保存することは、メモリを節約するために、これを必要としないときは、これらのコンテンツを破棄することができるからです.デフォルトでは、バッファ内のNSDisccardable Conteentオブジェクトは、そのコンテンツが破棄されると、キャッシュポリシーを変更することができますが、削除されます.一つのNSDisccardable Contentがキャッシュに入れられたら、オブジェクトが取り外されたときに、キャッシュはdiscardContentIfPossible方法を呼び出す.
NSCacheと可変集合にはいくつかの点があります.
NSCacheクラスは、システムメモリを過剰に使わないように各種の自動削除ポリシーを組み合わせています.他のアプリケーションにメモリが必要な場合、システムは自動的にこれらのポリシーを実行します.これらのポリシーを呼び出すと、メモリの占有を最小限に抑えるために、キャッシュからオブジェクトを削除します.NSCacheはスレッドセキュリティであり、キャッシュ領域をロックする必要なく、異なるスレッドにキャッシュのオブジェクトを追加、削除、および照会することができる.NSMuttable Dictionaryオブジェクトと違って、キャッシュオブジェクトはkeyオブジェクトをコピーしません.これらの特性はNSCache類にとって必要であり、メモリを解放する必要がある場合、キャッシュは非同期的にバックグラウンドで自分自身を自動的に修正することを決定しなければならないからである.
キャッシュ制限
NSCacheは、バッファの最大メンテナンスの対象の個数を限定するなど、バッファのサイズを制限するいくつかの属性を提供する.以下のように声明します
@property NSUInteger countLimit
デフォルトの値は0で、数量を制限しないことを表します.ただし、これは厳密な制限ではないので注意が必要です.キャッシュの数がこの数を超えると、キャッシュの中の1つのオブジェクトはすぐに破棄されるかもしれません.または、後で、永遠に破棄されないかもしれません.具体的には、キャッシュの実現の詳細に依存します.
また、NSCacheは、total CostLimit属性を提供し、キャッシュが維持できる最大メモリを限定している.その声明は以下の通りである
@property NSUInteger totalCostLimit
デフォルトの値も0です.制限がないことを表します.キャッシュにオブジェクトを追加すると、オブジェクトのバイトサイズなどの消耗(cost)を指定できます.このオブジェクトをキャッシュに追加すると、キャッシュ全体がtotal CostLimitの値を超えて消費され、キャッシュは、total CostLimit値を下回るまで、自動的にいくつかのオブジェクトを廃棄する.ただし、廃棄されたオブジェクトの順序は保証されません.
特に、total CostLimitも厳密な制限ではなく、その戦略はcount Limitと同じである.
アクセス方法
NSCacheは、NSMutable Dictionaryのようなkey−valueペアにアクセスする方法のセットを提供する.以下の通りです
- (id)objectForKey:(id)key

- (void)setObject:(id)obj forKey:(id)key

- (void)removeObjectForKey:(id)key

- (void)removeAllObjects
このように、NSMutable Dictioryとは違って、keyオブジェクトをコピーしないことです.
また、私たちはオブジェクトを格納する際に、次のように消耗値を指定できます.
- (void)setObject:(id)obj forKey:(id)key cost:(NSUInteger)num
この消耗値はキャッシュ中のすべてのオブジェクトの合計を計算します.メモリが制限されている場合、または合計消費量が制限された最大合計消費量を超えている場合、キャッシュはいくつかのオブジェクトを除去するために廃棄プロセスを開くべきである.しかし、このプロセスは、オブジェクトを廃棄する順序を保証することはできません.その結果、もし私たちがこの消耗値を操作して、いくつかの特殊な行為を実現しようとすれば、結果は私たちのプログラムを損なう可能性があります.通常、この消耗値は対象のバイトサイズです.これらの情報が既成のものでないなら、キャッシュを使用するコストを増加させるため、計算に行くべきではない.私たちが利用可能な値転送がない場合は、直接0を渡すか、あるいは-setObject:forKey:方法を使うか、この方法は消費値を入力する必要がない.
NSDiscardable Contentプロトコル
NSDiscardable Contectは、このプロトコルを実装する目的は、私たちのオブジェクトが使用されていないときに、より少ないメモリを占めるように廃棄することができます.
一つのNSDisccardable Controntオブジェクトのライフサイクルは一つの「counter」変数に依存します.一つのNSDisccardable Contentオブジェクトは実際にメモリブロックを整理することができます.このメモリはオブジェクトが現在他のオブジェクトに使用されているかどうかを記録しています.このメモリが読み込まれている場合、または必要とされている場合、そのカウンタ変数は1以上です.これを使用しない場合は、カウンタ変数は0になります.counter変数が0に等しい場合、現在の時点でメモリが緊張していれば、メモリブロックは破棄されます.
これらのコンテンツを破棄するために、オブジェクトのdiscardContentIfPossible方法を呼び出すことができ、この方法の声明は以下の通りである.
- (void)discardContentIfPossible
このようにカウンタ変数が0に等しいと関連メモリが解放されます.カウンタ変数が0でないと、この方法は何もしません.
デフォルトでは、NSDisccardable Controntオブジェクトのcounter変数の初期値は1であり、対象がメモリ管理システムによって直ちに解放されないことを確保する.この点から、counter変数の状態を追跡する必要があります.そのために.協議は二つの方法を表明しました.begin ContintentAccessとendContententAccess.
このうち、Begin ContintAccessを呼び出すとオブジェクトのcounter変数(+1)が増加し、オブジェクトが破棄されないことを確認することができます.この方法は次のように声明しています.
- (BOOL)beginContentAccess
私たちは通常、オブジェクトが必要とされたり、使用される時にこの方法を呼び出します.具体的な実装クラスは、オブジェクトが廃棄されている場合にこれらのメモリを再作成するかどうかを決定し、再作成が成功したらYESに戻ります.プロトコルの実装者は、NSDisccardable Contentオブジェクトが使用されていますが、そのBegin Contect Accessメソッドを呼び出していない場合は、例外を投げるべきです.
関数の戻り値がYESであれば、メモリを破棄しても利用可能であり、アクセスに成功したことを示します.そうでないとNOを返します.また、この方法は、実装クラスにおいて実装されなければならないことに留意されたい.
begin ContintAccessに対応するのはendContentAccessです.メモリを破棄してアクセスしない場合に呼び出します.その声明は以下の通りである
- (void)endContentAccess
この方法は対象のカウンタ変数を減少させ、通常はオブジェクトのカウンタ値を0に戻します.このようにオブジェクトの内容が必要でない場合は、それを廃棄します.
NSCache類はキャッシュが自動的に廃棄されたオブジェクトを廃棄するかどうかを識別する属性を提供しており、その宣言は以下の通りである.
@property BOOL evictsObjectsWithDiscardedContent
YESに設定すると、対象のメモリが破棄された時に対象を破棄します.デフォルトはYESです
NSCacheDelegate代理
NSCacheオブジェクトには、次のような代理属性があります.
@property(assign) id< NSCacheDelegate > delegate
NSCacheDelegateエージェントを実装するオブジェクトは、キャッシュからオブジェクトを除去する際に、いくつかの特定の動作を実行するので、プロキシオブジェクトは、以下の方法を実装することができる.
- (void)cache:(NSCache *)cache willEvictObject:(id)obj
なお、このプロキシ方法ではcacheオブジェクトを変更することができない.
結び目
実際、私たちがよく使うSDWebImageの画像ダウンロードライブラリのキャッシュメカニズムはNSCacheによって実現されます.「Effective Objective-C 2.0」では、NSCacheの使用を一編の内容で紹介しています(第50条:キャッシュ構築時にNS Cacheを使用してNSDictionaryではなくNS Cacheを使用しています).キャッシュ機構を構築する必要があるなら、NSDictionaryではなくNSCacheを使用するべきであり、メモリの占有を低減し、メモリの最適化の目的を達成することができる.