present的UINavigationController推透明VC时根视图消失问题
问题解决方法
核心原因
UINavigationController 默认会在 push 新视图控制器 时,将栈顶前一个控制器的 view 从自身视图层级中移除——这是出于性能优化的设计,因为默认导航控制器的 view 是不透明的,无需保留之前的视图。但你的场景中,导航控制器以 .overFullScreen 方式呈现,且要推送的是半透明控制器,需要保留 RootViewController 的视图来实现“透显”效果,默认行为就会导致 RootVC 视图被隐藏。
解决方案
步骤1:设置导航控制器视图为透明
初始化导航控制器时,添加一行代码设置其背景色为透明,确保底层视图能透出来:
let rootVC = RootViewController() let navVC = UINavigationController(rootViewController: rootVC) navVC.modalPresentationStyle = .overFullScreen navVC.isNavigationBarHidden = true navVC.view.backgroundColor = .clear // 新增:设置导航控制器视图透明 self.present(navVC, animated: true)
步骤2:自定义导航控制器,保留前视图层级
创建自定义导航控制器,重写 pushViewController 和 popViewController 方法,手动保留栈顶前一个控制器的视图在层级中:
class CustomNavigationController: UINavigationController { override func pushViewController(_ viewController: UIViewController, animated: Bool) { // 推送前,把当前栈顶控制器的视图插入到导航控制器视图的最底层 topViewController?.view.map { view.insertSubview($0, at: 0) } super.pushViewController(viewController, animated: animated) } override func popViewController(animated: Bool) -> UIViewController? { let poppedVC = super.popViewController(animated: animated) // 弹出后,移除被弹出控制器的视图 poppedVC?.view.removeFromSuperview() return poppedVC } }
之后将初始化导航控制器的代码改为使用自定义类:
let navVC = CustomNavigationController(rootViewController: rootVC)
补充说明
- 如果你不需要全局自定义导航控制器,也可以在 RootViewController 的
pushViewController调用前,手动将自身视图添加到导航控制器视图的底层:
let vc = TransparentViewController() self.navigationController?.view.insertSubview(self.view, at: 0) self.navigationController?.pushViewController(vc, animated: true)
但这种方式需要在 pop 时手动移除当前视图,不如自定义导航控制器的方式优雅。
内容的提问来源于stack exchange,提问作者Arnab Ahamed Siam
相关产品推荐
相关产品推荐

