关于didMoveToParentViewController:作用及视图所有权变更响应的疑问
didMoveToParentViewController:的作用解析 你已经熟悉添加子视图控制器的标准流程:
- 调用容器VC的
addChildViewController:,告知UIKit容器开始接管子VC的管理 - 将子VC的根视图加入容器的视图层级
- 添加约束定义子VC根视图的尺寸与位置
- 调用子VC的
didMoveToParentViewController:
针对文档里提到的该方法用于「让子视图控制器有机会响应视图所有权的变更」,以及这个方法的实际作用,下面详细解释:
一、「响应视图所有权变更」到底指什么
这里的「视图所有权变更」,核心是子VC的管理归属关系发生了转移:子VC从之前无父VC管理、或由其他VC管理的状态,正式转为当前容器VC负责管理。
这个变更会带来一系列连锁状态变化:
- 子VC的
parentViewController属性会正式指向容器VC - 子VC的生命周期会和容器VC绑定(比如容器进入后台、回到前台时,子VC会同步收到对应的生命周期回调)
- 子VC的视图层级正式并入容器的视图树,成为容器视图体系的一部分
而「响应」就是说,子VC可以在这个时机,针对归属变化做定制化处理:比如初始化和容器相关的交互逻辑、更新依赖父VC的状态、注册/注销和容器关联的通知等。
二、didMoveToParentViewController:的实际作用
根据苹果官方文档的定义,这个方法是UIKit给子VC提供的生命周期回调钩子,核心作用分为两点:
1. 完成容器与子VC的关联闭环
调用addChildViewController:时,UIKit会自动触发子VC的willMoveToParentViewController:,但不会自动调用didMoveToParentViewController:——这一步需要开发者手动调用,用来告诉UIKit:容器和子VC的关联流程已经全部完成(视图添加、约束设置都已搞定)。此时UIKit会完成最后一步状态同步,确保子VC的parent属性正确赋值,后续的生命周期回调也能正常传递。
2. 给子VC提供自定义逻辑的执行时机
子VC可以重写这个方法,在里面处理和父VC关联后的初始化工作:
- 比如子VC需要依赖父VC的某个属性初始化数据,就能在这里获取父VC引用并执行初始化
- 如果子VC要和父VC建立代理交互,也可以在这里完成代理设置
- 还能在这里启动和视图层级绑定的任务(比如入场动画、依赖视图的网络请求)
举个简单的Objective-C示例:
- (void)didMoveToParentViewController:(UIViewController *)parent { [super didMoveToParentViewController:parent]; // 仅当父VC存在时,执行关联后的逻辑 if (parent) { // 初始化依赖父VC的数据 self.dataSource = parent.dataSource; // 设置与父VC的交互代理 self.delegate = parent; // 启动视图入场动画 [self startIntroAnimation]; } }
另外要注意:在移除子VC的流程中,调用removeFromParentViewController:时,UIKit会自动调用子VC的didMoveToParentViewController:nil,此时子VC可以在这里做清理工作(比如移除监听、释放依赖父VC的资源)。
内容的提问来源于stack exchange,提问作者WisleyDee

