在视图控制器中,是否有必要在viewDidUnload期间在子视图上调用removeFromSuperview?

Dav*_*d H 8 cocoa-touch objective-c uiviewcontroller

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

- (void)viewDidUnload {
  [super viewDidUnload];
  ... snipped ...
  [_tableBannerView removeFromSuperview];
  TT_RELEASE_SAFELY(_tableBannerView);
  [_tableOverlayView removeFromSuperview];
  TT_RELEASE_SAFELY(_tableOverlayView);
  ... snipped ...
}
Run Code Online (Sandbox Code Playgroud)

我理解这种想法背后的原因:如果你打电话[self.view addSubview:_aView]loadView,你应该叫[_aView removeFromSuperview]viewDidUnload.问题是,这似乎没有必要.当视图控制器的视图被释放时,其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
Run Code Online (Sandbox Code Playgroud)

上面的代码产生以下输出:

viewController loadView
view init
view retain
view release
viewDidAppear
viewController dealloc
view release
view dealloc
Run Code Online (Sandbox Code Playgroud)

如您所见,当视图控制器的主视图被释放时,其子视图也会被释放.

另外,iOS开发者库[说明](http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/BasicViewControllers/BasicViewControllers.html#//apple_ref/doc/uid/TP40007457-CH101-SW4): "在内存不足的情况下,默认的UIViewController行为是释放存储在view属性中的视图对象(如果当前未使用该视图)." 另外:"如果使用声明的属性来存储对视图的引用,并且该属性使用retain语义,则为其分配nil值就足以释放视图."

因此,如果释放视图会自动释放其子视图,是否真的有必要removeFromSuperview在此期间调用viewDidUnload

Sim*_*Lee 3

不,没有必要,正如您所说的那样,dealloc 会为您做到这一点:)(长篇大论,简短的回答)。