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

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) {}
}

问题原因

你当前的代码存在三重导航栏冲突:

  1. SwiftUI的NavigationView自带导航栏(显示返回按钮)
  2. 你把SimpleViewController包装在了UINavigationController里,多了一层UIKit导航栏
  3. SimpleViewController内部还手动创建并添加了一个UINavigationBar

多重叠加导致你的红色导航栏被压在SwiftUI的返回按钮栏下方。

解决方案

方案一:利用SwiftUI导航栏统一管理(推荐)

移除UIKit侧的重复导航栏相关代码,让SwiftUI的NavigationView负责导航栏的显示:

  1. 修改SimpleViewController,移除手动创建的导航栏:
class SimpleViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white // 可选:添加背景色便于区分
        self.navigationItem.title = "Title"
        // 移除手动创建UINavigationBar的代码
    }
}
  1. 修改SimpleViewRepresentable,直接返回SimpleViewController而非包装在UINavigationController中:
struct SimpleViewRepresentable: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> SimpleViewController {
        SimpleViewController()
    }
    
    func updateUIViewController(_ uiViewController: SimpleViewController, context: Context) {}
}

这样跳转后,SwiftUI的导航栏会自动整合返回按钮和SimpleViewController的标题,两者处于同一栏。

方案二:使用UIKit的UINavigationController管理

如果必须依赖UIKit的导航控制器,需要隐藏SwiftUI的导航栏避免冲突:

  1. 同样先修改SimpleViewController,移除手动创建的导航栏:
class SimpleViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        self.navigationItem.title = "Title"
        // 移除手动创建UINavigationBar的代码
    }
}
  1. 修改主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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 08:27:34