こんなビューを作り、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