如何在混合开发项目中从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
相关产品推荐
相关产品推荐

