こんなビューを作り、View構成とそれぞれのViewの retainCountを出してみた。
"display RetainCount" を押した時の処理(UIViewController内)
- (void)displayRetainCountOfView:(UIView*)view level:(int)level { NSMutableString* indent = [NSMutableString string]; for (int i=0; i < level; i++) { [indent appendString:@" "]; } for (UIView* subview in [view subviews]) { NSLog(@"%@[%@ retainCount]: %d", indent, [subview class], [subview retainCount]); if ([[subview subviews] count] > 0) { [self displayRetainCountOfView:subview level:level+1]; } } } -(IBAction)display:(id)sender { NSLog(@"[self.view retainCount]: %d", [self.view retainCount]); [self displayRetainCountOfView:self.view level:0]; }
再帰的に回してサブビューも含めて表示している。
結果はこう。
[self.view retainCount]: 4 [UILabel retainCount]: 2 [UIRoundedRectButton retainCount]: 7 [UIButtonLabel retainCount]: 3 [UISwitch retainCount]: 2 [_UISwitchSlider retainCount]: 3 [UIImageView retainCount]: 3 [UIImageView retainCount]: 3 [UIView retainCount]: 3 [UILabel retainCount]: 3 [UILabel retainCount]: 3 [UIImageView retainCount]: 3 [UISlider retainCount]: 2 [UIImageView retainCount]: 3 [UIImageView retainCount]: 3 [UIImageView retainCount]: 3 [UIProgressView retainCount]: 2 [UITableView retainCount]: 2 [UIImageView retainCount]: 3 [_UITableViewSeparatorView retainCount]: 3 [_UITableViewSeparatorView retainCount]: 3 [_UITableViewSeparatorView retainCount]: 3 [UIImageView retainCount]: 3 [UISegmentedControl retainCount]: 2 [UISegment retainCount]: 3 [UISegmentLabel retainCount]: 3 [UIImageView retainCount]: 2 [UISegment retainCount]: 3 [UISegmentLabel retainCount]: 3 [UIImageView retainCount]: 2 [UIRoundedRectButton retainCount]: 2 [UIButtonLabel retainCount]: 3 [UITextField retainCount]: 2 [UITextFieldRoundedRectBackgroundView retainCount]: 3 [UIImageView retainCount]: 3 [UIImageView retainCount]: 3 [UIImageView retainCount]: 3 [UIImageView retainCount]: 3 [UIImageView retainCount]: 3 [UIImageView retainCount]: 3 [UIImageView retainCount]: 3 [UIImageView retainCount]: 3 [UIImageView retainCount]: 3 [UIImageView retainCount]: 3 [UIImageView retainCount]: 3 [UIImageView retainCount]: 3 [UIImageView retainCount]: 2
メインのビューに配置したコントロールの retainCount は 2となっている(一つはsuperviewによるもので、もう一つは不明)。
"diplay retainCount" ボタンのみ retainCountが 7となっているのがわかる。action-targetで接続するとその管理下におかれ、増えているのだと思われる。
[UIRoundedRectButton retainCount]: 7
- - - -
基本的に UIViewController.view 上に配置されたコントロールは、その UIViewController が破棄された時に UIViewController.view が release され、芋づる式にすべて開放(release)される。この為、これらのコントロールを UIViewController 内で使う場合、メモリのオーナーシップは考えなくて良いはず。
(例) @propety (nonatomic, assign) IBOutlet UILabel* label;
逆に reatain してしまった場合、その UIViewController がメモリ解放の責任の一旦を担わなければならない。
(例) @propety (nonatomic, retain) IBOutlet UILabel* label;
開放のタイミングは dealloc 以外に、UIViewController の場合はその生存期間と viewのそれとが異なるのでそれを考慮する必要がある。具体的にはメモリ不足が発生すると didReceiveMemoryWarning が呼ばれ、そのタイミングで viewが開放される。retainしている場合はこの時に開放しないと UIViewControllerのOultet参照が残ったままになってしまう。
(ただ、その後 viewの再生成で再び Outletが再設定されるので、その時に古い参照が開放される。なので viewの破棄・再作成毎に発生するメモリリークは起こっても限定的?)
。。。この辺りを現在検証中。
Responses
Leave a Response