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

如何在混合开发项目中从SwiftUI View返回至UIKit ViewController?

从SwiftUI视图返回原UIKit ViewController的几种实现方案

方案1:用SwiftUI环境自带的dismiss动作

如果你的UIKit控制器是通过导航栈push,或者直接present的方式打开SwiftUI的UIHostingController,直接用SwiftUI的环境变量就能搞定返回,不用额外传值:

struct MySwiftUIView: View {
    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        VStack {
            Button("返回") {
                dismiss()
            }
        }
    }
}

这个方法会自动适配打开方式:如果是push进来的,就执行导航栈的pop;如果是present的,就执行dismiss,省心又通用。

方案2:闭包回调让UIKit自己处理返回

要是返回时需要带数据或者执行一些额外逻辑(比如刷新原控制器的数据),给SwiftUI视图传个闭包是更灵活的选择:

先定义带闭包参数的SwiftUI视图:

struct MySwiftUIView: View {
    let onBack: () -> Void
    
    var body: some View {
        VStack {
            Button("返回") {
                onBack()
            }
        }
    }
}

然后在原UIKit控制器里打开时,把返回逻辑写在闭包里:

// 原UIKit控制器里的代码
let swiftUIView = MySwiftUIView { [weak self] in
    // 这里根据打开方式选对应的操作
    // push进来的就pop
    self?.navigationController?.popViewController(animated: true)
    // 如果是present进来的就dismiss
    // self?.dismiss(animated: true)
}
let hostingVC = UIHostingController(rootView: swiftUIView)
navigationController?.pushViewController(hostingVC, animated: true)

记得加[weak self]防止循环引用。

方案3:直接获取UIKit导航栈(不推荐)

这种方式耦合性很高,只适合简单场景用:通过UIApplication拿到当前窗口的导航控制器,直接调用pop。

struct MySwiftUIView: View {
    var body: some View {
        VStack {
            Button("返回") {
                guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
                      let navVC = windowScene.windows.first?.rootViewController as? UINavigationController else {
                    return
                }
                navVC.popViewController(animated: true)
            }
        }
    }
}

如果你的应用有多个窗口或者复杂的导航结构,这个方法很容易出问题,尽量不用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 05:21:28