调用popToRootViewController后切换Tab,subVC未触发viewDidDisappear的根本原因解析
问题根本原因解析
这是个非常典型的UIKit运行循环(RunLoop)与视图生命周期调度相关的问题,咱们一步步拆解:
核心逻辑:UIKit的视图操作并非完全同步执行
popToRootViewControllerAnimated: 虽然是同步调用的方法,但它内部并没有立刻完成所有视图层级变更和生命周期回调——UIKit会把视图移除、生命周期方法触发这些操作,打包到当前RunLoop的后续执行阶段(比如通过CATransaction或者RunLoop的beforeWaiting阶段)去处理,哪怕你传了animated:NO也是如此。
立刻切换Tab带来的冲突
当你在pop之后马上调用 self.selectedIndex = 1,这个Tab切换操作会直接触发UITabBarController的视图层级大变更:此时UIKit会优先处理Tab切换的逻辑,把原来Tab0的NavigationController及其子视图(包括还没完成pop流程的subVC)直接从屏幕上移除。
在这个过程中,UIKit的事件调度机制会认为:subVC的消失是因为Tab切换导致的父容器被隐藏,而不是因为pop操作被弹出——因此原本该由pop触发的viewDidDisappear回调就被跳过了。
为什么两层dispatch_async能解决问题?
两层主队列的dispatch_async本质是把Tab切换的操作推迟到当前RunLoop之后的第二个RunLoop周期执行:
- 第一层
dispatch_async:让任务等待当前RunLoop的所有待处理UI操作(包括pop带来的视图移除、生命周期回调)执行完毕; - 第二层
dispatch_async:再往后推一个周期,确保UIKit完全完成了pop流程的所有收尾工作(比如subVC的viewDidDisappear已经被调用),此时再执行Tab切换就不会干扰之前的生命周期回调了。
简单来说,就是给了UIKit足够的“缓冲时间”去处理pop的后续逻辑,再执行Tab切换操作。
内容的提问来源于stack exchange,提问作者bolizhou
相关产品推荐
相关产品推荐

