propertyとretainとautoreleaseと
Objective-Cの@property (retain)なプロパティへのautoreleaseされているオブジェクトの代入ではまったのでメモしておきます。
自分のクラスの中ではselfを使わないとプロパティ経由にはならない
@interface MyClass { SomeObject *_prop; } @property (nonatomic, retain) SomeObject *_prop; @end @implementation MyClass @synthesize _prop; - (void) func:(SomeObject *) prop { self._prop = prop; //propのretainCountが+1される _prop = prop; //propertyのsetterを経由しないで_propにアクセスするためretainされない } @end
autoreleaseされているオブジェクトを継続的に使う場合は自分でretainする必要がある
@interface MyClass2 { SomeObject *_prop2; } @end - (void) func2 { _prop2 = [[SomeClass getAutoreleaseObj] retain]; //自分のクラス内で使い続けることをretainで明示する _prop2 = [SomeClass getAutoreleaseObj]; //この場合イベントループに戻ったときに解放されてしまう }
retainしないで代入した場合はautorelease poolが解放されるタイミングで解放されてしまいます。
感覚的にはfunc2メソッド内でしか使えないと思ったほうがいいです。
retainするpropertyにautoreleaseされたオブジェクトを代入する
最後にこの2つを合わせるとどうなるか。
@interface MyClass3 { SomeObject *_prop3; } @property (nonatomic, retain) SomeObject *_prop3; @end @implementation MyClass3 @synthesize _prop3; - (void) func3 { self._prop3 = [SomeClass getAutoreleaseObj]; //propertyのsetterでretainされる _prop3 = [[SomeClass getAutoreleaseObj] retain]; //直接メンバ変数にアクセスするので自分でretainする必要がある } @end
プロパティ経由なら自分でretainを書いてはいけないし、直接メンバ変数に代入する場合はretainする必要があります。
個人的にはクラス内での代入は下のパターン(自分でretainを書く方法)の方が分かりやすいと思います。
とはいえselfを付けないとsetterを経由しない、ということを知らないと「なんでpropertyでretainしてるのにさらにretainする必要があるの??」と誤解する僕のような人がいるかもしれないのでまとめてみました。