在视图控制器中,在viewDidUnload期间是否需要调用removeFromSuperview以移除子视图?

8

许多人说在视图控制器的 viewDidUnload 方法中,必须通过调用 removeFromSuperview 方法来删除子视图。例如,Three20 这样做:

- (void)viewDidUnload {
  [super viewDidUnload];
  ... snipped ...
  [_tableBannerView removeFromSuperview];
  TT_RELEASE_SAFELY(_tableBannerView);
  [_tableOverlayView removeFromSuperview];
  TT_RELEASE_SAFELY(_tableOverlayView);
  ... snipped ...
}

我理解这种信念背后的原因:如果你在loadView中调用[self.view addSubview:_aView],那么你应该在viewDidUnload中调用[_aView removeFromSuperview]。然而事实是,这似乎并不必要。当视图控制器的视图被释放时,它的dealloc方法会自动释放所有子视图。我的测试代码显示,当父视图被释放时,子视图会自动被释放:

@interface TestView : UIView
@end

@implementation TestView
- (id)retain {
    NSLog(@"view retain");
    return [super retain];
}
- (void)release {
    NSLog(@"view release");
    [super release];
}
- (id)init {
    NSLog(@"view init");
    return (self = [super init]);
}
- (void)dealloc {
    NSLog(@"view dealloc");
    [super dealloc];
}
@end

@interface TestViewController : UINavigationController
@end

@implementation TestViewController
- (void)loadView {
    NSLog(@"viewController loadView");
    [super loadView];
    [self.view addSubview:[[TestView new] autorelease]];
}
- (void)viewDidUnload {
    NSLog(@"viewController viewDidUnload");
    [super viewDidUnload];
}
- (void)viewDidAppear:(BOOL)animated {
    NSLog(@"viewDidAppear");
    [super viewDidAppear:animated];
    [self dismissModalViewControllerAnimated:YES];
}
- (void)dealloc {
    NSLog(@"viewController dealloc");
    [super dealloc];
}
@end

上述代码生成以下输出:
viewController loadView
view init
view retain
view release
viewDidAppear
viewController dealloc
view release
view dealloc

正如您所看到的,当视图控制器的主视图被释放时,它的子视图也会被释放。
此外,iOS开发者库声明:“在低内存情况下,默认的UIViewController行为是释放存储在视图属性中的视图对象,如果该视图当前未被使用。” 另外:“如果您使用一个已声明的属性来存储对视图的引用,并且该属性使用保留语义,将nil值分配给它就足以释放该视图。”
因此,如果释放视图会自动释放其子视图,那么在viewDidUnload期间调用removeFromSuperview是否真的有必要呢?
2个回答

3
不需要,正如你所说,dealloc方法会为你完成这个任务 :)(长篇回答,简短回答)。

1

在我的项目中,我发现这是必要的。我的viewController有一个主视图(像它们所有的一样),在这种情况下,它是使用xib定义的(不是以编程方式分配和添加为子视图)。这个视图有IBOutlets的子视图在视图控制器中。如果在viewDidUnload上,我只是将IBOutlet属性设置为nil(self.mySubView = nil),那么该子视图上的dealloc不会被调用。如果我先将其从其父视图(主视图)中删除,然后dealloc就会被调用。


1
你有任何示例代码来说明这个吗?既然你提到了XIBs,把项目放在Github上会更有帮助。谢谢。 - David H

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接