2009-08-18 14 views
2

imageWithDataを使用してインスタンス化しているUIImageがあります(データは[NSData dataWithContentsOfFile:]を使用してバンドルからロードされます)。iPhoneのビューに描画するときのメモリ管理

私はそのようにのようなイメージを描いています:

NSData *imageData = [NSData dataWithContentsOfFile:fileLocation]; 
UIImage *myImage = [UIImage imageWithData:imageData]; 

//These lines are superfluous from what I can tell, replacing with 
//UIImage *myImage = [UIImage imagedNamed:imageName]; very soon. 

[myImage drawAtPoint:CGPointMake(0,0)]; 
//myImage will be released at the end of the run loop 

私の質問はこれです:作成したUIImageが自動解放されます。 UIImageがビューに描画され、UIImageの存在が解消されたときのメモリの状況はどうなりますか。明らかに、視覚的には、画像は文脈に描かれているので、そこにはまだあります。

UIImageが有効で、ビューに描画されている場合はメモリ使用量が倍になりますが、UIImageの割り当てが解除された後にUIImageが1つしか存在しない場合と同じ量に戻りますか?


ここで別のルートを下ります。

イメージをインスタンス化するために[UIImage imageNamed:]を使用した場合、UIImageクラスには独自のイメージ・キャッシュがあり、作成されるUIImageインスタンスの数に関係なく、特定のイメージの真のインスタンスが1つだけ保持されますその1つの画像を表す)。

私の他の質問は、コンテキストに描画してUIimageを解放すると(キャッシュのループ終了時に自動解放によって)、キャッシュ内の画像はどうなりますか?イメージはキャッシュ内のメモリを消費しますか?それは他のUIImageインスタンスがそれを使用していないので削除されますか?

ご協力いただきありがとうございます!

+0

もっと徹底したコードを教えてください。 –

+0

私が正直であれば、提供するコードはそれほど多くありません。私はそこにないものを追加します。 – Jasarien

答えて

1

ここでは単純なコードから始めて、実際に問題が発生している場所を最適化することをお勧めします。あなたが記述しているような空間最適化の種類は、深刻な時間の問題を引き起こす可能性があります(例:-drawRect:のUIImageを再作成するのは非常に高価です)。

  • まず、私が言ったように、-drawRect:に高価な仕事をしていると注意してください:それはのは、様々な質問を通して見てみましょう、と述べました。どのくらいの頻度で呼び出されるか、またいつ呼び出されるかはほとんど変わりません。新しいUIImageの作成(特にディスクからの読み込みが必要な場合など)は、UIのパフォーマンスに重大な影響を与えます。

  • これはあなたの-drawRect:にはさらに多くのものがあると仮定していますが、これは正しいですか? UIImageViewは、速度とメモリの両方でここで行ったことに最適化されています。しかし、あなたのビューがはるかに複雑な場合は、多くのサブビューを作成するよりも自分でイメージを描画する方が良いです。

  • -drawAtPoint:を呼び出すと、コピーはビットマップ表現(完了した他の図とブレンド)されます。メモリ使用量に関しては元のUIImageとは無関係です。あなたはもう一方のものを交換することはできません。ビットマップ表現に必要なメモリは、ビューサイズとビット深度の関数であり、変更することはできません。 UIImageが描画された後にUIImageが存在するかどうかは気にしません。

  • -imageNamed:はあなたのためにキャッシュしますが、一般的には良い選択です。メモリ不足の状況ではキャッシュをクリアしないことに注意してください。 UIImage自体は、ファイルからロードされた場合に、その基になるデータを透過的にダンプします(とにかく余分な表現をダンプします)。 UIImageリファレンスには、これがどのように行われたかに関する情報が含まれています。

  • これらのイメージの周りのパフォーマンス(スペースや時間)が非常に懸念され、UIImageの機能は必要ない場合は、CGImagesで作業する必要があります。彼らはUIImageほど柔軟ではなく、コードはより複雑ですが、より効率的です。つまり、UIImageはほとんどの目的に適しています。

+0

UIImageViewは最適化されていません。利便性のためだけにあります。 UILabelでも同じことが起こります。 – rpetrich

+0

主張する(「サブクラス化ノート」を参照)。 drawRect:をバイパスします。代わりにそれを掘り起こさないでください、しかし、彼らは空想的なことをしていると主張します。 –

1

コンテキストに描画すると、コンテキストにはイメージへの参照が保持されません。代わりに、描画はコンテキストのピクセルの実際のビットを配置するので、UIImage(またはNSString、NSPathなどに描画されたもの)への参照は必要ありません。

については、実際にリリースされることはありません。あなたが取得したものはリリースされてはならず、リリースされるべきではありませんが、キャッシュされたイメージはまだ残っている可能性があります。

+0

私は自分でそれを公開しません。 [UIImage imageNamed:]は、自動リリースされたUIImageインスタンスを返します。実行ループの終わりにそれ自身をリリースします。私が知りたいことは、キャッシュされたイメージがそれを参照するUIImageの割り当て解除時に解放されるかどうかです。 – Jasarien

+0

キャッシュされたイメージを解放するかどうかは指定されません。私はそれがないと思います。それはシステムでそうするかもしれません - それは 'didReceiveMemoryWarning'と同じですが、私の知る限りではありません。 –

+0

imageNamed:システムはdidReceiveMemoryWarningと同等のシステムにキャッシュされますが、2.xでは3.0 - のみで、キャッシュが決してフラッシュされないバグがありました。 – rpetrich

0

実際は、UIImageインスタンス自体の作成場所によって異なります。これがUIViewサブクラスの場合、-drawRect:または-initWithFrame:などのUIImageを作成していますか?一度イメージをロードすると(initやsetterを保持しているなど)、問題はありません。しかし、-drawRect:で何度も何度もイメージを作成している場合は、パフォーマンス上の問題が発生します。

+0

私がここに持っている主な問題は、drawRectまで使わない画像を保持したくないということです。 ビューは非常に頻繁に再描画されないため、drawRect内でイメージをインスタンス化することはそれほど問題ではないと思います。 私がinitでインスタンス化すると、イメージは使用されていないと思っていてもメモリを消費しています。これは私には意味がありません。 – Jasarien

+0

あなたが言ったように、それはイメージをキャッシュしますが、メモリが逼迫するとキャッシュをフラッシュする可能性があるので、私は '[UIImage imageNamed:]'に行きます。このようにしても参照は得られますが、実際のデータ自体はフラッシュされる可能性があります。 UIImageはすべての苦労を世話します。 – jbrennan