切换标签页后init()调用后ViewController生命周期方法未触发
切换标签页后Push视图控制器时生命周期方法(loadView/viewDidLoad)未触发的问题
问题重现
从主标签页界面通过以下代码调用CommonListViewController:
self?.navigator.go(module: CommonListBuilder(mode: .vacation), mode: .push(animated: false))
CommonListBuilder的build()方法实现:
func build() -> BaseViewController { CommonListViewController(interactor: CommonListInteractor(mode: mode), mode: mode) }
已确认build()和CommonListViewController的init方法均被执行:
init( interactor: CommonListInteractorProtocol, mode: CommonListMode ) { self.interactor = interactor self.mode = mode self.adapter = CommonListTableAdapter(mode: mode) self.searchAdapter = CommonListSearchAdapter() super.init() interactor.sendMetrics(event: .openScreen, params: mode.paramsForOpenScreen) }
但loadView、viewDidLoad等生命周期方法均未触发,且该问题仅在切换标签页后出现,首次启动时无异常。
可能的原因及解决方案
1. 标签页导航栈被意外替换或释放
切换标签页时,若当前标签页对应的UINavigationController实例被重新初始化、释放,或其控制器栈被错误清空/替换,会导致新push的控制器无法关联到活跃导航栈,进而无法触发生命周期。
- 排查:检查标签页切换逻辑(如
UITabBarController的viewControllers赋值逻辑),确保切换后当前标签页的UINavigationController是未被替换的活跃实例。 - 验证:push前打印
self?.navigator对应的导航控制器内存地址,对比首次启动和切换标签页后的地址是否一致。
2. 自定义导航器(navigator)的push逻辑状态异常
如果自定义navigator在标签页切换后,内部维护的当前导航控制器引用失效,会导致仅创建了控制器实例,但未真正将其添加到导航栈。
- 排查:查看
navigator.go(module:mode:)的实现,确认push时是否正确获取当前活跃的UINavigationController,并执行了pushViewController(_:animated:)方法。 - 修复示例:确保navigator始终从活跃的标签页中获取导航控制器:
func go(module: ModuleBuilder, mode: NavigationMode) { let vc = module.build() guard let tabBarVC = UIApplication.shared.keyWindow?.rootViewController as? UITabBarController, let currentNav = tabBarVC.selectedViewController as? UINavigationController else { return } switch mode { case .push(let animated): currentNav.pushViewController(vc, animated: animated) // 其他导航逻辑分支 } }
3. BaseViewController的生命周期逻辑被破坏
如果BaseViewController的init()或生命周期方法被错误重写,可能导致子类的生命周期触发逻辑失效,且仅在特定场景(如标签页切换后)暴露问题。
- 排查:检查
BaseViewController的init()、loadView方法,确保正确调用父类方法(如super.init()),且未手动将view设置为nil或干扰视图加载流程。
4. 控制器未被添加到视图层级
虽然init方法执行,但如果navigator的push逻辑存在分支错误,导致未实际执行pushViewController操作,控制器未被加入导航栈,系统不会触发其生命周期。
- 排查:在
navigator.go方法中添加日志,确认pushViewController是否被调用,以及传入的控制器实例是否正确。 - 验证:push后打印当前导航栈的
viewControllers数组,查看是否包含CommonListViewController实例。
内容的提问来源于stack exchange,提问作者MaryLitv21
相关产品推荐
相关产品推荐

