SwiftUI项目中如何从UIViewController跳转到其他视图
实现方案
核心思路是通过闭包将UIKit侧的点击事件透传到SwiftUI层,由SwiftUI的导航体系处理跳转逻辑,以下是完整可运行的修改后代码:
import SwiftUI import UIKit // 要跳转的目标SwiftUI视图 struct TargetView: View { var body: some View { Text("这是跳转后的目标视图") .navigationTitle("目标页") } } struct ContentView: View { // 导航路径,用来控制跳转 @State private var navPath = NavigationPath() var body: some View { NavigationStack(path: $navPath) { ViewControllerWrapper(controller: MyViewController()) { // 收到UIKit侧的点击回调,执行跳转 navPath.append("targetView") } .navigationTitle("首页") .navigationDestination(for: String.self) { pathValue in if pathValue == "targetView" { TargetView() } } } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } class MyViewController: UIViewController{ // 对外暴露的点击回调闭包 var onGoToAnotherView: (() -> Void)? lazy var goToAnotherViewButton: UIButton = { let button = UIButton(type: .custom) button.layer.cornerRadius = 5 button.backgroundColor = .systemYellow button.titleLabel?.font = UIFont.systemFont(ofSize: 22) button.setTitle("Go", for: .normal) button.addTarget(self, action: #selector(goToAnotherView), for: .touchUpInside) return button }() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white let stackView = UIStackView(arrangedSubviews: [goToAnotherViewButton]) stackView.axis = .vertical stackView.spacing = 20 stackView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(stackView) NSLayoutConstraint.activate([ stackView.leftAnchor.constraint(equalToSystemSpacingAfter: view.leftAnchor, multiplier: 2), view.rightAnchor.constraint(equalToSystemSpacingAfter: stackView.rightAnchor, multiplier: 2), stackView.topAnchor.constraint(equalToSystemSpacingBelow: view.topAnchor, multiplier: 2), ]) } @objc func goToAnotherView() { // 触发回调,通知SwiftUI层执行跳转 onGoToAnotherView?() } } struct ViewControllerWrapper: UIViewControllerRepresentable{ func makeUIViewController(context: UIViewControllerRepresentableContext<ViewControllerWrapper>) -> UIViewController { guard let controller = controller as? MyViewController else { return UIViewController() } // 将Wrapper的回调赋值给MyViewController的回调属性 controller.onGoToAnotherView = goAction return controller } func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<ViewControllerWrapper>) { } let controller:UIViewController? // 接收外部传入的点击回调 let goAction: (() -> Void) typealias UIViewControllerType = UIViewController }
关键改动说明
- 给
MyViewController新增了onGoToAnotherView闭包属性,点击按钮时触发该闭包将事件向外传递 - 给
ViewControllerWrapper新增了goAction闭包属性,在创建ViewController时把闭包赋值给MyViewController的对应属性,打通UIKit到SwiftUI的事件传递链路 - SwiftUI层新增
NavigationStack和导航路径状态,收到回调后修改导航路径即可完成跳转
如果需要兼容iOS15及更早版本,把NavigationStack替换为NavigationView,使用isActive状态变量控制跳转即可,事件传递的逻辑完全一致。
内容的提问来源于stack exchange,提问作者neco
相关产品推荐
相关产品推荐

