I’m using UIHostingController
in order to present a SwiftUI
flow (more or less 5 screens) inside a UIKit
based app. But at the end of the SwiftUI
flow, I need to return to the last ViewController presented. Does anyone know how to accomplish that behavior?
To put the problem in simple words:
Screen A (UIViewController
) -> Screen B (SwiftUI
view) -> Screen C (SwiftUI
view) -> Screen D (SwiftUI
view). Screen D needs to return to Screen A.
Notes:
SwiftUI
views useNavigationView
andNavigationLink
's.- I looked at https://stackoverflow.com/a/61926030/6938899 but the answer solves the problem to return to Screen B (still a
SwiftUI
view).
EDIT
Added simplified version in code to explain the problem better:
import UIKit
import SwiftUI
// MARK: - Wrapper to use SwiftUI views inside UIKit
class SwiftUIWorkflowViewController: UIHostingController<SwiftUIWorkflowView> {
override init(rootView: SwiftUIWorkflowView) {
super.init(rootView: rootView)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
// MARK: - ViewModel for SwiftUI workflow
public final class SwiftUIWorkflowViewModel: ObservableObject { }
// MARK: - UIKit screen
class ScreenAViewController: UIViewController {
//... other stuff
private func navigateToSwiftUIFlow() {
let swiftUIWorkflowViewModel = SwiftUIWorkflowViewModel()
let deviceNetworkingVC = SwiftUIWorkflowViewController(
rootView: SwiftUIWorkflowView(viewModel: swiftUIWorkflowViewModel)
)
navigationController?.pushViewController(deviceNetworkingVC, animated: true)
}
}
// MARK: - Beggining of SwiftUI views
public struct SwiftUIWorkflowView: View {
@Environment(\.presentationMode) private var presentationMode
@ObservedObject var viewModel: SwiftUIWorkflowViewModel
// MARK: - Init
public init(viewModel: SwiftUIWorkflowViewModel) {
self.viewModel = viewModel
}
// MARK: - Views
public var body: some View {
NavigationView {
ScreenBView(onBack: { self.presentationMode.wrappedValue.dismiss() })
}
.environmentObject(self.viewModel)
}
}
// MARK: - Screen B (SwiftUI)
public struct ScreenBView: View {
@EnvironmentObject var viewModel: SwiftUIWorkflowViewModel
var onBack: (() -> Void)? = nil
public init(onBack: (() -> Void)? = nil) {
self.onBack = onBack
}
public var body: some View {
VStack {
Text("Screen B")
Button {
self.onBack?()
} label: {
Text("Go back to UIKit screen")
}
NavigationLink(destination: ScreenBView()) {
Text("Go to screen C")
}
}
}
}
// 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!")
// here I need a way to return to ScreenAViewController.
}
}
}