私はObjective-cを初めて使用し、いつにするかなどの基本的なメモリ管理ルールを知っていretain
release
autorelease
ます。しかし、コードを自動解放プールにラップする必要があるのはいつですか、またその理由はわかりません。
4 に答える
他のパフォーマンスの最適化と同様に、通常、メモリ使用量が多く、プロファイリング(たとえば、Instrumentsを使用)によってソリューションとして追加の自動解放プールが表示される場合にのみ、コードに自動解放プールを追加する必要があります。
とはいえ、自動解放プールのタイトなループで多数の一時オブジェクトを作成するコードをラップすることができます。デフォルトの自動解放プールは、実行ループサイクルの終了時に排出されます。したがって、コード内のforループの各反復で多数の一時オブジェクトを作成している場合、デフォルトの自動解放プールは、ループ全体が実行されるまで排出されません。つまり、作成したすべての一時オブジェクトを合計すると、一時的なメモリ使用量が多い(「最高水準点」と呼ばれることもあります)。ループの各反復をでラップして@autoreleasepool
、そのループの反復で作成された不要な自動解放された一時オブジェクトをより早く解放することができます。
以前の回答を拡張するには:
自動解放プールは、release
追加されたオブジェクトにメッセージを自動的に送信するために使用されます。
iOS または Cocoa プログラムでは、自動解放プールがメイン スレッドで自動的に作成され、実行ループの最後に排出されます。
つまり、別のスレッドで自動解放されたオブジェクトを使用する場合、自動解放プールは必須です。
したがって、スレッドを何らかのメソッドにデタッチする場合は、スレッド化されたコードを自動解放プール内にラップします。そうしないと、スレッドで作成された自動解放オブジェクトがリークするだけです。
自動解放プールのもう 1 つの用途は、多くのメモリを使用するコードの部分を最適化することです。そのため、それらは実行ループの終了前に解放されます。
ただし、自動解放されたオブジェクトにのみ関係します。
例えば:
- ( void )test
{
NSMutableArray * a = [ [ NSMutableArray alloc ] init ];
[ a release ];
}
自動解放されたオブジェクトがないため、ここでは自動解放プールは必要ありません。
変数は、a
明示的に割り当てられて解放されたため、すぐに解放されます。
今これ:
- ( void )test
{
NSMutableArray * a = [ NSMutableArray arrayWithCapacity ];
}
ここでは、便利なコンストラクターを使用しています。つまり、そのオブジェクトの所有権を持っていません。
また、オブジェクトが現在の自動解放プール (存在する場合) に追加されたことも意味します。
したがって、この自動解放プールが空になると解放されるため、数サイクルかかる場合があります...
記述しているコードの一部が大量のメモリを使用している場合は、別の自動解放プールを使用できます。これにより、自動解放されたオブジェクトは、メソッドが返されたときに解放されます。
- ( void )test
{
@autoreleasepool
{
NSMutableArray * a = [ NSMutableArray arrayWithCapacity ];
}
}
自動解放されたすべてのオブジェクトは、技術的には自動解放プール内に配置されます。通常、メイン関数内に作成されたデフォルトのものがあります。デフォルト以外の自動解放プール内でのオブジェクトのラップに関しては、通常は最適化として行われます。
デフォルトの自動解放プールはアプリの実行ループ内で自動的に排出されるため、通常、明示的な自動解放プールを使用する必要はありません。ただし、イベント ハンドラーから返される前に多くの自動解放オブジェクトを作成するアプリがある場合、それらのオブジェクトのために大量のメモリが使用される可能性があります。したがって、コードを明示的な自動解放プール内にラップすると、自動解放されたオブジェクトはデフォルト プールではなくそこに配置されます。これにより、このプールを定期的に空にして、自動解放されたオブジェクトが蓄積されないようにすることができます。
ただし、独自の自動解放プール ブロックを使用する場合が 3 つあります。
コマンドライン ツールなど、UI フレームワークに基づかないプログラムを作成している場合。
多くの一時オブジェクトを作成するループを作成する場合。ループ内で自動解放プール ブロックを使用して、次の反復の前にこれらのオブジェクトを破棄できます。ループで自動解放プール ブロックを使用すると、アプリケーションの最大メモリ フットプリントを削減できます。
セカンダリ スレッドを生成する場合。