UIKit App中SwiftUI流程完成后如何返回对应UIViewController?
实现方案
你要实现从SwiftUI流程末尾直接返回屏幕A,本质上只需要把承载整个SwiftUI流程的SwiftUIWorkflowViewController从UIKit的导航栈中移除即可,不需要操作SwiftUI内部的Navigation栈。你已经定义了全局的SwiftUIWorkflowViewModel,完全可以用它作为跨页面的回调载体,不用逐层传递闭包。
具体修改步骤
- 第一步:给
SwiftUIWorkflowViewModel添加结束流程的回调属性
public final class SwiftUIWorkflowViewModel: ObservableObject { // 新增:结束整个SwiftUI流程的回调 var onFinishFlow: (() -> Void)? }
- 第二步:在屏幕A跳转时给回调赋值,实现pop逻辑
private func navigateToSwiftUIFlow() { let swiftUIWorkflowViewModel = SwiftUIWorkflowViewModel() // 给回调赋值,pop掉当前的HostingController即可回到屏幕A swiftUIWorkflowViewModel.onFinishFlow = { [weak self] in self?.navigationController?.popViewController(animated: true) // 如果需要更稳妥的直接回到屏幕A,也可以指定pop到对应VC: // if let screenA = self { // self?.navigationController?.popToViewController(screenA, animated: true) // } } let deviceNetworkingVC = SwiftUIWorkflowViewController( rootView: SwiftUIWorkflowView(viewModel: swiftUIWorkflowViewModel) ) navigationController?.pushViewController(deviceNetworkingVC, animated: true) }
- 第三步:在SwiftUI流程末尾的页面直接调用回调即可
// MARK: - Screen C (SwiftUI) public struct ScreenCView: View { @EnvironmentObject var viewModel: SwiftUIWorkflowViewModel public var body: some View { VStack { Text("Screen C - End of the SwiftUI flow!") // 新增返回按钮,直接调用回调 Button { viewModel.onFinishFlow?() } label: { Text("直接返回屏幕A") } } } }
补充说明
你之前查到的方案只能退回SwiftUI内部的页面,是因为它操作的是SwiftUI自身的Navigation栈,而整个SwiftUI流程是作为一个整体被UIKit的导航栈管理的,直接操作UIKit的导航栈移除对应的HostingController,就能一步回到屏幕A,SwiftUI内部的栈会随着HostingController的销毁自动清理。
另外注意你示例代码里的小问题:ScreenBView里的NavigationLink目的地现在写的是ScreenBView(),要改成ScreenCView()才能正常跳转到C页面。
内容的提问来源于stack exchange,提问作者Juan Manuel Gentili
相关产品推荐
相关产品推荐

