2010年5月12日水曜日

NSArrayとNSDictionaryのオーナーシップ

Objective-C 2.0ではガベージコレクションが導入されて、メモリ管理がだいぶシンプルになりましたが、iPhone開発ではその恩恵に預かれませんので、色々と気を使います。

NSArrayに要素を追加した時、NSArrayはその要素オブジェクトにretainメッセージを送ってオーナーシップを獲得します。NSArrayが解放された場合、格納されているオブジェクトすべてにreleaseメッセージが送られます。また、格納した要素をNSArrayから削除した場合、その要素にreleaseメッセージが送られます。

なので、こういう書き方をするのはちょいとよろしくありません。

NSArray *array = [[NSArray alloc] initWithObjects:
                     [[Foo alloc] init], [[Bar alloc] init],nil];
// なんらかの処理
[array release];

FooとBarをallocしてinitした時点で、このコードが書かれているオブジェクトがFooとBarそれぞれのオーナーになります。その後、array に追加しているので、array もこの2つの要素のオーナーシップを持ちます。

array を release する事で、Foo と Bar にもreleaseメッセージが送信され、retainCount が減るのですが、コードが書かれてるオブジェクトがまだオーナーシップを握っているため、破棄されません。このコードだと破棄しようもない。困った。

なので、律儀にこう書くのが吉。

Foo *foo = [[Foo alloc] init];
Bar *bar = [[Bar alloc] init];
NSArray *array = [[NSArray alloc] initWithObjects: foo, bar, nil];
[foo release];
[bar release];
// なんらかの処理
[array release];

これじゃどんくさい、という人はautoreleaseにまかせてしまうとか。

NSArray *array = [[NSArray alloc] initWithObjects:
                     [[[Foo alloc] init]autorelease],  [[[Bar alloc] init]autorelease], nil];
// なんらかの処理
[array release];

iPhone環境はautoreleaseは結構まめにやってくれる事がこないだ判ったので、これで安心でしょう。

NSDictionaryの場合、こちらもNSArrayとほぼ同様なのですが、値はそのまま参照してretainメッセージを送りますが、キーはオブジェクトをコピーして保持するそうです。

私はどんくさい方が好みです。実生活ではぐうたらであまり掃除は得意でないんですが。

0 件のコメント:

コメントを投稿