My app is a hybrid of UIKit & SwiftUI. I have a use case where a user may need to tap on a Button from a SwiftUI.View but push to a UIViewController or another UIHostingController.
My project uses Storyboard.
I'm using UINavigationController & UITabBarController.
There are two scenarios I am looking at.
1.) From my initial launch on my home screen, I can tap a button and within its action I have:
let vc = UIHostingController(rootView: RootView())
self.navigationController?.pushViewController(vc, animated: true)
This works as expected.
2.) I tap on a different tab and it defaults to my SwiftUI RootView which is hosted in a custom UIHostingController which I use in my Storyboard. Here, if I tap on a button to trigger the push, it doesn't push. I just see the View I am on update.
I'm also using a custom UINavigationController. From my Storyboard, the tabs relationship goes to the custom UINavigationController & then its root is the appropriate UIViewController. In one scenario though it's my custom UIHostingController so I can load a SwiftUI View initially from the tab selection.
Here is what I have tried doing to handle push to a View Controller from my SwiftUI View:
final class AppData: ObservableObject {
weak var window: UIWindow? // Will be nil in SwiftUI previewers
init(window: UIWindow? = nil) {
self.window = window
}
public func pushViewController(_ viewController: UIViewController, animated: Bool = true) {
let nvc = window?.rootViewController?.children.first?.children.first as? UINavigationController
nvc?.pushViewController(viewController, animated: animated)
}
}
// This is what is triggered from the Button action.
func optionSelected(option: String) {
if let optionId = Common.getIDByOption(option: option) {
let vc = UIHostingController(rootView: RootView())
appData.pushViewController(vc, animated: true)
}
}
What happens:
- I do see the data change, but it's all on the same View I am already on.
- I need to push to the new
UIHostingController.
If you're mixing
UIKitandSwiftUIin a way whereUITabBarControllerandUINavigationControllerare handling the navigation. I advise you to cutNavigationViewandNavigationLink. The reason behind it is simple.SwiftUI.Viewwill be recreated on each switch to tab. Hence, you would start from the begining. You could walk around it, but in this situation, easier will be useUINavigationController.Let's assume you're app has two tabs. I would put
SwiftUI.ViewinUIHostingControllerand then inUINavigationController. InSwiftUI.ViewI would put closurelet onTap: () -> Voidwhich would be called whenever you need to push nextUIHostingControllerorUIViewControllertoUINavigationController.Example