iOS SwiftUI中从View跳转ViewController时合并导航栏与返回按钮
问题描述
我有一个SwiftUI的View,通过NavigationLink跳转到一个被UIViewControllerRepresentable包装的ViewController。这个ViewController自身带有导航栏,但跳转后,它的导航栏显示在返回按钮下方。如何让ViewController的导航栏与返回按钮显示在同一栏中?
原代码
var body: some View { NavigationView(content: { NavigationLink { SimpleViewRepresentable() } label: { Text("Present View Controller") } }) } class SimpleViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let navBar = UINavigationBar(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 44)) view.addSubview(navBar) navBar.backgroundColor = .red self.navigationItem.title = "Title" } } struct SimpleViewRepresentable: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> UINavigationController { let vc = UINavigationController(rootViewController: SimpleViewController()) vc.setNavigationBarHidden(false, animated: true) return vc } func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {} }
问题原因
你当前的代码存在三重导航栏冲突:
- SwiftUI的
NavigationView自带导航栏(显示返回按钮) - 你把
SimpleViewController包装在了UINavigationController里,多了一层UIKit导航栏 SimpleViewController内部还手动创建并添加了一个UINavigationBar
多重叠加导致你的红色导航栏被压在SwiftUI的返回按钮栏下方。
解决方案
方案一:利用SwiftUI导航栏统一管理(推荐)
移除UIKit侧的重复导航栏相关代码,让SwiftUI的NavigationView负责导航栏的显示:
- 修改
SimpleViewController,移除手动创建的导航栏:
class SimpleViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white // 可选:添加背景色便于区分 self.navigationItem.title = "Title" // 移除手动创建UINavigationBar的代码 } }
- 修改
SimpleViewRepresentable,直接返回SimpleViewController而非包装在UINavigationController中:
struct SimpleViewRepresentable: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> SimpleViewController { SimpleViewController() } func updateUIViewController(_ uiViewController: SimpleViewController, context: Context) {} }
这样跳转后,SwiftUI的导航栏会自动整合返回按钮和SimpleViewController的标题,两者处于同一栏。
方案二:使用UIKit的UINavigationController管理
如果必须依赖UIKit的导航控制器,需要隐藏SwiftUI的导航栏避免冲突:
- 同样先修改
SimpleViewController,移除手动创建的导航栏:
class SimpleViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white self.navigationItem.title = "Title" // 移除手动创建UINavigationBar的代码 } }
- 修改主View的
NavigationLink,隐藏SwiftUI侧的导航栏:
var body: some View { NavigationView(content: { NavigationLink { SimpleViewRepresentable() .navigationBarHidden(true) // 隐藏SwiftUI的导航栏 } label: { Text("Present View Controller") } }) }
SimpleViewRepresentable保持原有代码即可,此时UIKit的UINavigationController会生成包含返回按钮和标题的统一导航栏。
内容的提问来源于stack exchange,提问作者Mozz
相关产品推荐
相关产品推荐

