You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 11:21:19