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

从已呈现的ViewController推送控制器时导航栏不显示

解决导航栏隐藏后推送新控制器无法显示的问题

我通过UINavigationController以模态方式呈现了ViewController A,并隐藏了其导航栏。但推送ViewController B时,即使在B中设置self.navigationController?.setNavigationBarHidden(false, animated: false)也无法让导航栏显示,相关代码及背景信息如下:

呈现ViewController A的Objective-C代码

AppDelegate* delegate = [AppDelegate applicationDelegate];
UIStoryboard *story = [UIStoryboard storyboardWithName:STORYBOARD_MAIN bundle:nil];
SelectionViewController *tutorial = [story instantiateViewControllerWithIdentifier:@"SelectionViewController"];
tutorial.providesPresentationContextTransitionStyle = YES;
tutorial.definesPresentationContext = YES;
[tutorial setModalPresentationStyle:UIModalPresentationOverCurrentContext];
tutorial.delegate = self;

UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:tutorial];
navController.modalPresentationStyle = UIModalPresentationFullScreen;
[navController.navigationBar setHidden:YES];
navController.providesPresentationContextTransitionStyle = YES;
navController.definesPresentationContext = YES;
[navController setModalPresentationStyle:UIModalPresentationOverCurrentContext];
[delegate.tabBarController presentViewController:navController animated:YES completion:NULL];

推送ViewController B的代码(Objective-C调用Swift控制器)

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"AppDetail" bundle:nil];
DetailViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"DetailViewController"];
[self.navigationController pushViewController:vc animated:YES];
[[self navigationController] setNavigationBarHidden:NO];

补充信息

  • ViewController A基于Objective-C编写,ViewController B基于Swift编写
  • 两个控制器分别位于不同的Storyboard中

解决方法

1. 用导航控制器的官方方法管理导航栏状态

你当前直接修改navController.navigationBar.hidden属性,这会绕过UINavigationController的内部状态管理逻辑,导致后续推送控制器时状态无法同步更新。

将呈现导航控制器时的隐藏代码替换为:

// 替换 [navController.navigationBar setHidden:YES];
[navController setNavigationBarHidden:YES animated:NO];

2. 调整推送B时的导航栏设置时机

可以选择两种方式确保导航栏正确显示:

方式一:在A中推送前/后设置

调整推送代码的顺序,先设置导航栏显示再推送(或配合动画同步执行):

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"AppDetail" bundle:nil];
DetailViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"DetailViewController"];
// 先设置导航栏显示,再推送,保持动画一致
[self.navigationController setNavigationBarHidden:NO animated:YES];
[self.navigationController pushViewController:vc animated:YES];

方式二:在B的生命周期方法中设置

在B的Swift代码中,重写viewWillAppear方法强制显示导航栏:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.navigationController?.setNavigationBarHidden(false, animated: animated)
}

如果需要返回A时重新隐藏导航栏,可以在viewWillDisappear中恢复:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    self.navigationController?.setNavigationBarHidden(true, animated: animated)
}

3. 清理冗余的模态样式设置

你同时给ViewController A和它所在的导航控制器设置了UIModalPresentationOverCurrentContext,这会导致上下文冲突。建议只保留导航控制器的模态样式设置,移除A的相关代码:

// 移除以下三行冗余代码
// tutorial.providesPresentationContextTransitionStyle = YES;
// tutorial.definesPresentationContext = YES;
// [tutorial setModalPresentationStyle:UIModalPresentationOverCurrentContext];

内容的提问来源于stack exchange,提问作者Rahul Vyas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 17:50:37