objective-cでretainCountが増えるとき減るときの確認

Objective-ciPhoneiPadアプリ開発をしているが、GCのない言語をまともに使ったことがないので混乱している。
頭を整理するためにViewBasedApplicationを使って試してみる。

基本

- (void)viewDidLoad {
    [super viewDidLoad];
	
	UIView *a = [[UIView alloc] init];
	LOG(@"a retainCount:%d",[a retainCount]); // => 1
	
	[self.view addSubview:a];
	LOG(@"a retainCount:%d",[a retainCount]); // => 2 増えた
	
	[a removeFromSuperview];
	LOG(@"a retainCount:%d",[a retainCount]); // => 1
}
  • allocしたときに増える
  • addSubviewしたとき増える
  • removeFromSuperviewしたときに減る

addSubviewで増えたcountはいつ減るのか

さらにaにsubview bが、bにsubview cがついたとき

  • UIView a
    • UIview b
      • UIView c
- (void)viewDidLoad {
    [super viewDidLoad];
	
	UIView *a = [[UIView alloc] init];
	[self.view addSubview:a];
	LOG(@"a retainCount:%d",[a retainCount]); // => 2
	
	UIView *b = [[[UIView alloc] init] autorelease]; 
	UIView *c = [[[UIView alloc] init] autorelease]; 
	[a addSubview:b];
	[b addSubview:c];
	LOG(@"a retainCount:%d",[a retainCount]); // => 2
	LOG(@"b retainCount:%d",[b retainCount]); // => 2
	LOG(@"c retainCount:%d",[c retainCount]); // => 2
	
	
	[a removeFromSuperview];
	LOG(@"a retainCount:%d",[a retainCount]); // => 1 (減った)
	LOG(@"b retainCount:%d",[b retainCount]); // => 2 (ここでは減らない)
	LOG(@"c retainCount:%d",[c retainCount]); // => 2
	
	[a release];
	LOG(@"b retainCount:%d",[b retainCount]); // => 1 (減った)
	LOG(@"c retainCount:%d",[c retainCount]); // => 2 (ここでは減らない)
}
  • aにsubviewがついてもaのcountは増えない(増えるように見える時があるのはなんだろ)
  • bはaがリリースされるとretainCountが減る([a removeFromSuperview]のタイミングではない)
  • cはbのdeallocが呼ばれないのでreleaseされないのだろう

MutableArrayやMutableDictionaryで増えたcountはいつ減るのか

- (void)viewDidLoad {
    [super viewDidLoad];
	
	NSMutableArray *d = [NSMutableArray array];
	NSObject *obj1 = [[NSObject alloc]init];
	LOG(@"d retainCount:%d",[d retainCount]); // => 1
	LOG(@"obj1 retainCount:%d",[obj1 retainCount]); // => 2
	
	[d addObject:obj1];
	LOG(@"d retainCount:%d",[d retainCount]); // => 1
	LOG(@"obj1 retainCount:%d",[obj1 retainCount]); // => 2
	
	[d release];
	LOG(@"obj1 retainCount:%d",[obj1 retainCount]); // => 1
}
  • addObjectするとobj1は増える
  • MutableArrayを削除すればobj1は減る

autorelease

retainCountが1になったら殺すという死刑宣告。retainしてやれば延命できる。

あとは

Objective-C プログラミング言語:メモリ管理を熟読するのが早い

結論

  • alloc, copy(なんちゃらcopy, copyなんちゃらを含む) , retain, addSubview, addObject(その他addなんちゃら)をすると増える
  • addなんちゃらで増えたcountはaddしたオブジェクトが解放されれば減る

疑問

autoreleaseプールの仕組み。例えば

NSObject *a;
for(int i=0; i<100; i++){
 a = [[[NSObject alloc] init] autorelease];
}

は全部リリースされるのかどうか不安