iOS14下SwiftUI设置navigationBarHidden(false)导航栏不显示问题
问题原因
iOS 14 存在 SwiftUI 导航栏状态继承的已知缺陷:父页面设置隐藏导航栏后,子页面单独设置的navigationBarHidden(false)修饰符无法覆盖父级的隐藏状态,该逻辑在 iOS 15 及以上版本已被官方修复,因此仅 iOS 14 会出现导航栏不显示的异常。
修复方案
方案1:状态变量控制导航栏显隐(纯SwiftUI实现,推荐)
通过父页面的状态变量动态控制导航栏显隐,避免状态继承冲突:
- 父页面新增导航栏显隐状态变量:
@State private var hideNavigationBar = true
- 父页面原有固定的导航栏隐藏修饰符改为绑定该状态:
.navigationBarHidden(hideNavigationBar)
- 给跳转的NavigationLink添加点击时切换状态的逻辑:
NavigationLink(destination: getInTouchView) { Text(NSLocalizedString("Get in touch", comment: "Get in touch")) .mp_white_outline_pill_button() } .simultaneousGesture(TapGesture().onEnded { hideNavigationBar = false })
- 父页面添加返回恢复逻辑,避免返回后父页面导航栏显示异常:
.onDisappear { hideNavigationBar = true }
方案2:UIKit强制控制(兜底方案)
如果纯SwiftUI方案不生效,可通过底层UIKit接口强制修改导航栏状态,适配iOS14的特殊逻辑:
- 先添加获取当前导航控制器的SwiftUI扩展:
extension View { var currentNavigationController: UINavigationController? { UIApplication.shared.windows.first?.rootViewController?.children.first as? UINavigationController } }
- 在GetInTouchView的根视图上添加生命周期控制逻辑:
ZStack { // 原有视图代码 } .onAppear { guard #available(iOS 15, *) else { currentNavigationController?.setNavigationBarHidden(false, animated: false) return } } .onDisappear { guard #available(iOS 15, *) else { currentNavigationController?.setNavigationBarHidden(true, animated: false) return } } // 原有其他修饰符保留
额外说明
- iOS14对导航类修饰符的顺序敏感度更高,可尝试将
.navigationBarHidden(false)调整到navigationTitle、navigationBarTitleDisplayMode等修饰符之前,提升兼容性。 - 你之前用空
NavigationLink修复自动pop的方案是iOS14多NavigationLink场景下的标准兼容方案,保留即可。
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

