読者です 読者をやめる 読者になる 読者になる

Obj-C再入門・プロパティ、autorelease

いままで不真面目にObjective-Cを触ってきたので、こりゃいかんと思い、再入門する。

プロパティ、autorelease

こういうクラスがあるとする。

@interface Hoge : NSObject{
  MyObj *obj;
}
@property(nonatomic, retain) MyObj *obj;

@end

"retain"となっているのは、プロパティに値を代入すると、オブジェクトがそのプロパティを自動的にretainしてくれる、という宣言。

プロパティobjに値を代入するときは・・

MyObj obj1 = [[MyObj alloc] init];
hoge.obj = obj1;
[obj1 release];

とすればよい。hoge.objに代入された値は即座にretainされるので、obj1は不要となる。なので代入後はすぐさまobj1をreleaseしている。

ところで毎回オブジェクトをreleaseするのはめんどい。というわけで、NSAutoReleasePoolの出番。こいつのインスタンスをあらかじめ作っておけば、
上記コードは以下のように書ける。

MyObj obj1 = [[[MyObj alloc] init] autorelease];
hoge.obj = obj1;

こう書いておけば、NSAutoReleasePoolの解放時にobj1がreleaseされる。おおくのiPhoneアプリではmain関数内でNSAutoReleasePoolを作っておいてくれているので、そいつにまかせておいてもOk(実際にはあんまり使った事無いが・・)

あと、ちょっとはまったのがhoge.objの値を差し替える処理。hoge.objはretainされているので、hoge.objに別のオブジェクトを代入する場合は、まず元々hoge.objに代入されていたオブジェクトをrelaseしなきゃなー、と思っていたが、そんなことはしなくてよい。以下のように単純に書けば良い。

MyObj *obj1 = [[[MyObj alloc] init] autorelease];
hoge.obj = obj1;

MyObj *obj2 = [[[MyObj alloc] init] autorelease];
hoge.obj = obj2;

実はプロパティの宣言時に"retain"を指定すると、hoge.objに値を代入するタイミングで、既存の値を事前にreleaseする、というところまで勝手にやってくれる。便利だー。