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

如何在UIKit的UIHostingController承载的SwiftUI视图中使用navigationDestination

解决SwiftUI navigationDestination 在UIKit导航栈中失效的问题

方法1:将SwiftUI视图嵌入NavigationStack中

navigationDestination是SwiftUI NavigationStack专属的导航API,无法直接与UIKit的UINavigationController联动。你可以把目标SwiftUI视图包裹在NavigationStack里,再交给UIHostingController,同时隐藏UIKit的导航栏避免双重导航栏冲突:

// UIKit Part
let rootSwiftUIView = NavigationStack {
    MySwiftUIView()
}
let hostingController = UIHostingController(rootView: rootSwiftUIView)
// 隐藏UIKit导航栏,使用SwiftUI的NavigationStack导航栏
hostingController.navigationItem.hidesBackButton = true
navigationController?.pushViewController(hostingController, animated: true)

// SwiftUI Part
struct MySwiftUIView: View {
    @State private var isPresented = false
    
    var body: some View {
        VStack {
            Button("Navigate") {
                isPresented = true
            }
            .navigationDestination(isPresented: $isPresented) { 
                Text("New View")
                    .navigationTitle("Detail")
            }
        }
        .navigationTitle("Home")
    }
}

方法2:通过回调让UIKit处理导航

如果不想引入SwiftUI的NavigationStack,可以在SwiftUI视图中定义回调闭包,触发时通知UIKit侧push新的视图控制器:

// UIKit Part
let hostingController = UIHostingController(rootView: MySwiftUIView(onNavigate: {
    let detailHostingController = UIHostingController(rootView: Text("New View"))
    navigationController?.pushViewController(detailHostingController, animated: true)
}))
navigationController?.pushViewController(hostingController, animated: true)

// SwiftUI Part
struct MySwiftUIView: View {
    let onNavigate: () -> Void
    
    var body: some View {
        VStack {
            Button("Navigate") {
                onNavigate()
            }
        }
        .navigationTitle("Home")
    }
}

方法3:使用UIViewControllerRepresentable桥接导航逻辑

如果需要更灵活的跨框架导航交互,可以自定义桥接组件,让SwiftUI能直接调用UIKit的导航能力:

// 桥接组件
struct NavigationBridge: UIViewControllerRepresentable {
    let navigationController: UINavigationController
    
    func makeUIViewController(context: Context) -> UIViewController {
        UIViewController()
    }
    
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
    
    static func dismantleUIViewController(_ uiViewController: UIViewController, coordinator: Coordinator) {}
    
    // 定义push方法
    func push<Content: View>(_ view: Content, animated: Bool = true) {
        let hostingController = UIHostingController(rootView: view)
        navigationController.pushViewController(hostingController, animated: animated)
    }
    
    // 注入SwiftUI环境的Modifier
    struct Provider: ViewModifier {
        let navigationBridge: NavigationBridge
        
        func body(content: Content) -> some View {
            content.environment(\.navigationBridge, navigationBridge)
        }
    }
}

// 扩展环境变量
extension EnvironmentValues {
    var navigationBridge: NavigationBridge? {
        get { self[NavigationBridgeKey.self] }
        set { self[NavigationBridgeKey.self] = newValue }
    }
}

private struct NavigationBridgeKey: EnvironmentKey {
    static let defaultValue: NavigationBridge? = nil
}

// 使用示例
// UIKit Part
guard let navController = navigationController else { return }
let bridge = NavigationBridge(navigationController: navController)
let rootView = MySwiftUIView().modifier(NavigationBridge.Provider(navigationBridge: bridge))
let hostingController = UIHostingController(rootView: rootView)
navController.pushViewController(hostingController, animated: true)

// SwiftUI Part
struct MySwiftUIView: View {
    @Environment(\.navigationBridge) private var navigationBridge
    
    var body: some View {
        VStack {
            Button("Navigate") {
                navigationBridge?.push(Text("New View"))
            }
        }
        .navigationTitle("Home")
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 10:15:01