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

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する必要があるの??」と誤解する僕のような人がいるかもしれないのでまとめてみました。