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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 08:06:02