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

iOS设置hidesBottomBarWhenPushed后Pop页面TabBar不显示问题

解决hidesBottomBarWhenPushed引发的TabBar异常隐藏问题

问题复现场景

  • UITabBarController的标签页为嵌套单个UIViewController的UINavigationController;
  • Push初始化时设置hidesBottomBarWhenPushed = true的VC2,TabBar正常隐藏;
  • VC2内按钮同时执行两个操作:全屏present VC3、pop当前VC2;
  • dismiss VC3回到初始页面后,TabBar仍保持隐藏状态,延迟present可修复但不符合需求。

问题根源

同一Runloop内同时执行pop和present操作,打乱了UITabBarController的状态评估逻辑,导致它未能正确识别当前栈顶控制器已无需隐藏TabBar。

解决方案

无需延迟present,只需确保present操作在pop动画完成后执行,让UITabBarController有足够时间更新状态。以下提供两种可行方案:

方案一:利用CATransaction监听pop动画完成

修改VC2的按钮点击事件,通过CATransaction的完成回调在pop结束后触发present:

class VC2: UIViewController {
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        
        hidesBottomBarWhenPushed = true
        
        navigationItem.leftBarButtonItem = UIBarButtonItem(systemItem: .close, primaryAction: UIAction(handler: { _ in
            let vc = UINavigationController(rootViewController: VC3())
            vc.modalPresentationStyle = .fullScreen
            
            // 监听pop动画完成后执行present
            CATransaction.begin()
            CATransaction.setCompletionBlock {
                self.navigationController?.present(vc, animated: true)
            }
            self.navigationController?.popViewController(animated: true)
            CATransaction.commit()
        }), menu: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .blue
    }
}

方案二:通过UINavigationControllerDelegate回调处理

让VC2遵守导航控制器代理协议,在pop完成后的回调中执行present:

class VC2: UIViewController, UINavigationControllerDelegate {
    private var pendingPresentVC: UIViewController?
    
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        
        hidesBottomBarWhenPushed = true
        navigationController?.delegate = self
        
        navigationItem.leftBarButtonItem = UIBarButtonItem(systemItem: .close, primaryAction: UIAction(handler: { _ in
            let vc = UINavigationController(rootViewController: VC3())
            vc.modalPresentationStyle = .fullScreen
            self.pendingPresentVC = vc
            
            self.navigationController?.popViewController(animated: true)
        }), menu: nil)
    }
    
    func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
        guard let pendingVC = pendingPresentVC else { return }
        navigationController.present(pendingVC, animated: true)
        pendingPresentVC = nil
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .blue
    }
}

两种方案均无需延迟操作,能确保dismiss VC3后TabBar正常显示,因为present操作会在pop动画完全结束后执行,UITabBarController有足够时间重新评估TabBar的显示状态。

内容的提问来源于stack exchange,提问作者Saren Inden

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 06:41:06