iOS开发疑问:子控制器视图添加后appear方法未调用但disappear正常?
代码场景
class TestPlatfromViewController: UIViewController { var webVC: MyViewController! override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .gray webVC = MyViewController() view.addSubview(webVC.view) } }
问题描述
push TestPlatfromViewController 后,将 MyViewController 的 view 添加到该控制器的 view 上。此时 MyViewController 的 viewWillAppear 与 viewDidAppear 并未被调用,但当 pop TestPlatfromViewController 时,MyViewController 的 viewWillDisappear 与 viewDidDisappear 却被正常触发。
根据苹果官方文档定义:
viewDidAppear:通知视图控制器其视图已添加到视图层级中viewDidDisappear:通知视图控制器其视图已从视图层级中移除
由此产生困惑:为什么 MyViewController 的 viewWillAppear 和 viewDidAppear 没有被调用?
原因解析
UIViewController 的生命周期方法(如 viewWillAppear/viewDidAppear)并非仅由 view 是否加入视图层级触发,核心在于是否建立了正确的父子控制器关系。
你当前的代码只是把子控制器的 view 直接添加到父视图上,但没有通过 UIKit 提供的正式流程建立父子控制器关联——缺少调用 addChild(_:) 和 didMove(toParent:) 这两个关键步骤。UIKit 只有在识别到合法的父子控制器关系时,才会自动触发子控制器的“出现类”生命周期方法。
而 pop 时触发“消失类”方法的原因是:当父控制器被从导航栈移除时,UIKit 会递归遍历整个视图层级中的所有 view,找到关联的视图控制器并调用其消失方法,这是一种自动清理机制,但这并不代表之前的出现流程是合法的。
正确实现方式
添加子控制器时必须遵循完整的父子控制器生命周期流程:
override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .gray webVC = MyViewController() // 1. 建立父子控制器关系 addChild(webVC) // 2. 添加子视图到父视图 view.addSubview(webVC.view) // 3. 设置子视图约束(根据需求调整) webVC.view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ webVC.view.topAnchor.constraint(equalTo: view.topAnchor), webVC.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), webVC.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), webVC.view.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) // 4. 告知子控制器已完成移动 webVC.didMove(toParent: self) }
这样 UIKit 就会自动调用 MyViewController 的 viewWillAppear 和 viewDidAppear 方法。
内容的提问来源于stack exchange,提问作者Roy

