24/7 twenty-four seven

iOS/OS X application programing topics.

NSAutoreleasePoolの動作について

3つめのコードがちょっと違います。

でもって本題ですが、Objective-CにはretainCountって物があって、それが0になると解放されるみたいです。(未だに良く理解してない)
そしてretainCountはalloc, init, retainなどで増えて、releaseで減るみたいです。

だいたい見つけた使い方等は以下の3つ。スーパーpreがおかしい...?

HOGE *hoge = [[HOGE alloc] init];

/* . . . */

[hoge release];

HOGE *hoge = [[[HOGE alloc] init] autorelease];

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
HOGE *hoge = [[HOGE alloc] init];
FOO *foo = [[FOO alloc] init];

/* . . . */

[pool resease];

1つめは使い終わったら自分で解放させる方法。
2つめは自動で解放させてくれる方法。
3つめは1つめと同じ考えですが、releaseまでに生成されたオブジェクトを解放させる(らしい)。

メモリ関係 - hijouguchiの日記

NSAutoreleasePoolは、プールが作られてから解放されるまで([[NSAutoreleasePool alloc] init]〜[pool resease])にautoreleaseメッセージが送られたオブジェクトをプールに登録します。

そして、NSAutoreleasePoolが解放(release)されるときに、それまでに登録された(autoreleaseされた)オブジェクトをすべて解放します。


つまり、オブジェクトにautoreleaseメッセージを送るのは、NSAutoreleasePoolにオブジェクトをaddしているということになります。
そうやって追加されたオブジェクトに対して、NSAutoreleasePoolは一斉にreleaseを送るという仕組みです。


だから3つめの例は、インスタンスにautoreleaseを送っていないので、プールが解放されてもオブジェクトにreleaseが送られないので、オブジェクトは解放されません。


正しくは下のようにする必要があります。

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
HOGE *hoge = [[[HOGE alloc] init] autorelease];
FOO *foo = [[[FOO alloc] init] autorelease];

/* . . . */

[pool resease];

ちなみにNSAutoreleasePoolはイベントループで自動的に生成と破棄を繰り返しているので、自分で作る必要はほとんどありませんが、
スレッドを使う場合はそのスレッド用に自分で用意する必要があります。


あとは、ループの中で一時オブジェクトを大量に作る場合ですね。
ループ中にメモリが解放されるようにNSAutoreleasePoolのブロックを作った方がいい場合があります。