クォーツキャッシングCGLayer
-
05-07-2019 - |
質問
CGLayerドキュメントから引用するには:
Quartzは、CGLayerオブジェクトを含む、再利用されるすべてのオブジェクトをキャッシュします。
大規模ページのメモリに問題があり、画面がオン/オフかどうかに基づいてビューを解放および再作成する簡単なメカニズムを実装しようとしています。
簡単にするために、ネットワーク要求の結果として作成され、どこかに配列に保存されたUIImageがたくさんあるとします。次のようにUIImageViewを作成します:
anImage = [anArray objectAtIndex:0];
UIImageView* imgView = [[UIImageView alloc] initWithImage:anImage];
[mainView addSubview:imgView]; // Quartz eats memory for view after first draw
[imgView release]; // owned by mainView now
[...] // wait a bit for draw cycle
[imgView removeFromSuperview]; // memory doesn't go down
imgView
がオフスクリーンになると、 removedFromSuperview
としてリリースされます。いいね?いいえ-Quartzに存在するCGLayerは、 anImage
がまだ存在するため削除されません。
どうすればこれを回避できますか?このシナリオでの唯一の方法は、異なるポインターアドレスを使用して、Quartzの背後でまったく同じイメージを作成し、古いイメージを削除することです。これを行う唯一の方法は、画像を「ディープコピー」する(UIImageはNSCodingを実装しない)か、ネットワーク経由で再度要求する(遅い)ことです。
私が考えているのは、画像をデータベースにsqlliteして、ビューが画面に表示されるたびにそれらを再取得する必要があるということです。
解決
ここで、imgViewを0から1に増やします。
UIImageView* imgView = [[UIImageView alloc] initWithImage:anImage];
次の行で、mainViewは参照カウントをインクリメントします。 (現在は2)
[mainView addSubview:imgView]; // Quartz eats memory for view after first draw
ここで、imgViewをリリースすると、参照カウントが1に戻ります。
[imgView release]; // owned by mainView now
メモリの問題はanImageとは関係ないと思います。 imgViewがサブビューである限り、そのオブジェクトは画面に描画する必要があるため、そのオブジェクトは解放されません。
次の行の意味は、プログラムでCGLayerに描画すると、描画したものをキャッシュしてQuartzに描画するため、同じものを常に再描画することはありません。本当にサブビューの追加とは関係ありません。
Quartzは、CGLayerオブジェクトを含む、再利用されるすべてのオブジェクトをキャッシュします。