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

如何从SwiftUI跳转带返回按钮的UINavigation式UIViewController?

解决SwiftUI与UIKit导航栏重叠问题

我明白你遇到的问题:用NavigationLink跳转到封装了UINavigationController的UIViewControllerRepresentable时,出现了两套导航栏——SwiftUI自带的导航栏有返回按钮,而你自己创建的UIKit导航栏没有,你想要保留UIKit的导航栏并添加返回按钮,同时隐藏SwiftUI的那一套。

下面是具体的解决方案,分两步走:

1. 修正UIKit视图封装代码,添加返回按钮回调

首先,你需要给UIKit的视图控制器添加返回按钮,并且通过Coordinator让它能通知SwiftUI关闭页面。同时要注意,不要把UINavigationController作为结构体的属性(结构体是值类型,容易重复创建),而是在makeUIViewController方法内创建:

struct UIKitVc: UIViewControllerRepresentable {
    // 定义关闭回调,用于UIKit通知SwiftUI返回
    var onDismiss: () -> Void
    
    // 创建Coordinator,处理UIKit与SwiftUI的交互
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    func makeUIViewController(context: Context) -> UINavigationController {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let viewController = storyboard.instantiateViewController(withIdentifier: "SearchResult") as! SearchResultViewController
        
        // 给UIKit的视图控制器添加自定义返回按钮
        let backButton = UIBarButtonItem(title: "返回", style: .plain, target: context.coordinator, action: #selector(Coordinator.dismiss))
        viewController.navigationItem.leftBarButtonItem = backButton
        
        // 用目标VC作为导航控制器的根视图
        let navigationController = UINavigationController(rootViewController: viewController)
        return navigationController
    }
    
    func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {}
    
    class Coordinator: NSObject {
        var parent: UIKitVc
        
        init(_ parent: UIKitVc) {
            self.parent = parent
        }
        
        // 触发SwiftUI的关闭动作
        @objc func dismiss() {
            parent.onDismiss()
        }
    }
}

2. 在SwiftUI中隐藏自带导航栏并绑定关闭动作

接下来,在使用NavigationLink(或navigationDestination)时,隐藏SwiftUI的导航栏,并绑定关闭回调,让UIKit的返回按钮能触发页面返回:

如果你使用的是iOS 16+的NavigationStack:

struct ContentView: View {
    @State private var isPresentingUIKitVc = false
    
    var body: some View {
        NavigationStack {
            Button("打开UIKit搜索结果页") {
                isPresentingUIKitVc = true
            }
            .navigationDestination(isPresented: $isPresentingUIKitVc) {
                UIKitVc(onDismiss: {
                    isPresentingUIKitVc = false
                })
                .navigationBarHidden(true) // 隐藏SwiftUI的导航栏
            }
        }
    }
}

如果你使用的是iOS 15及以前的NavigationView:

struct ContentView: View {
    @State private var isPresentingUIKitVc = false
    
    var body: some View {
        NavigationView {
            Button("打开UIKit搜索结果页") {
                isPresentingUIKitVc = true
            }
            .navigationLink(isActive: $isPresentingUIKitVc) {
                UIKitVc(onDismiss: {
                    isPresentingUIKitVc = false
                })
                .navigationBarHidden(true) // 隐藏SwiftUI的导航栏
            } label: {
                EmptyView()
            }
        }
    }
}

为什么原来会出现两套导航栏?

因为NavigationLink会自动将目标视图嵌入到SwiftUI的导航栈中,所以SwiftUI的导航栏会默认显示;而你在UIKitVc中又创建了一个独立的UINavigationController,两者叠加就出现了双导航栏的问题。通过.navigationBarHidden(true)可以完全隐藏SwiftUI的导航栏,同时我们手动给UIKit的导航栏添加了返回按钮,实现了符合你需求的导航体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 14:02:41