将VCB的View添加到VCA未用addChildViewController,为何自动调用生命周期方法?是否必用?
iOS子视图控制器生命周期与容器控制器使用问题
现有两个ViewController,分别为VCA和VCB,我需要将VCB的View添加到VCA的View中作为子视图。但我未使用
addChildViewController方法,而是直接调用[vca.view addSubview:vcb.view],却发现VCB的viewWillAppear、viewDidAppear方法被自动调用了。我想了解该现象的原因,同时想知道在添加其他ViewController的View作为子视图时,是否必须使用addChildViewController方法。相关代码如下:
// ViewControllerA.m - (void)showVCBView { ViewControllerB *vcb = [[ViewControllerB alloc] init]; [self.view addSubview:vcb.view]; }
一、直接添加View触发VCB生命周期方法的原因
当你访问vcb.view时,系统会自动触发VCB的loadView或viewDidLoad完成视图加载。而当这个视图被添加到已经处于显示状态的父视图(VCA的view此时已经在屏幕上)时,UIKit内部会检测到视图的window属性从nil变为非nil,且父视图处于可见状态,就会自动触发它所属ViewController的viewWillAppear:和viewDidAppear:方法——这是UIKit内置的视图状态同步逻辑。
二、是否必须使用addChildViewController
不是语法上的“必须”,但强烈推荐严格遵循这个规范,核心原因有这些:
- 生命周期不完整:如果不添加子控制器,VCB的
viewWillDisappear:、viewDidDisappear:等后续生命周期方法不会自动触发(比如VCA的view被隐藏或移除时,VCB的对应方法不会执行),导致VCB无法正确处理视图消失后的逻辑(比如停止动画、释放资源)。 - 内存风险:代码里vcb是局部变量,直接添加View后,VCB没有被VCA持有,会被提前释放,可能引发野指针崩溃。用
addChildViewController会让VCA持有VCB,保证其生命周期和容器控制器同步。 - 适配问题:UIKit的旋转、尺寸变化通知只会传递给当前ViewController层级内的控制器,未添加为子控制器的VCB收不到这些通知,容易出现布局错乱。
- 符合设计逻辑:系统自带的容器控制器(比如UINavigationController、UITabBarController)都是通过这种方式管理子控制器的,遵循规范能避免很多隐性问题。
正确的子控制器添加流程应该是:
- (void)showVCBView { ViewControllerB *vcb = [[ViewControllerB alloc] init]; [self addChildViewController:vcb]; [self.view addSubview:vcb.view]; // 按需设置子视图布局,比如frame或AutoLayout vcb.view.frame = self.view.bounds; [vcb didMoveToParentViewController:self]; }
移除时的对应流程:
- (void)removeVCBView { ViewControllerB *vcb = self.childViewControllers.firstObject; [vcb willMoveToParentViewController:nil]; [vcb.view removeFromSuperview]; [vcb removeFromParentViewController]; }
内容的提问来源于stack exchange,提问作者carol
相关产品推荐
相关产品推荐

