「iPhoneアプリのメモリ管理 その1」から間が空きましたが、その2です。
リファレンスカウンタでメモリの解放を判断する方式で、困ったシチュエーションが一つ出てきます。
メソッド内でメモリを確保して、そのポインタを返す場合、どのクラスでreleaseするかが難しくなってきます。
呼び出し元で解放するとすると、確保したクラスと解放するクラスが別になり、オブジェクト指向的に美しくない状態になりますし、確保したクラス側に、別途メモリを解放する為のメソッドを作ってもいいですが、呼び出し元のクラスから解放するためだけに呼び出すのも少し煩雑です。
このような状況でのコードを簡略にする為の仕組みがautoreleaseプールです。
例えば、NSStringクラスのstringWithFormatメソッドのような、スタティックなメソッド内でメモリを確保して、そのポインタを返すような場合、呼び出し元でretainしなければ、自然と解放されます。
これはautoreleaseプールを使っているからです。
autoreleaseプールを自前allocして、特定の範囲で確保したメモリを一括して解放するような使い方も出来ますが、デフォルトでひとつ用意されていて、メインのスレッド(RunLoop)の処理が終わる度に、自動でreleaseされます。
その為、確保したメモリをautoreleaseしておけば、メインの処理が終わった時の状況に応じて解放される事になります。(呼び出し元でretainされた場合はカウントが上がっているので解放されません。)
例えば何かしらのメモリを確保してポインタを返すような時は、以下のようにautoreleaseしておくと、確保したところで解放の責任も負っているような状態になり、別途解放の為のメソッドを作るより、コードが簡単になります。
+(id)something
{
return [[[Something alloc] init] autorelease];
}
今までの事をまとめると
1.allocしたクラスではrelease/autoreleaseを必ず行う。
2.他のクラスが確保してメモリ領域を、複数回のLoopに渡って使うクラスでは、必ずretainしておく。
3.retainしたものは必ずrelease/autoreleaseする。
ここまででメモリ管理の基本はOKだと思いますが、Objective-C特有の事で少しはまった部分があるので、また別途書きたいと思います。
※iPhoneアプリ開発に関する投稿を今から始めるiPhoneアプリ開発にまとめました。
最近のコメント