Reputation: 909
We're pushing to a SwiftUI
view embedded in a UIHostingViewController
in UIKit
land like this:
First making the UIViewController
:
func hostingController() -> UIViewController {
let swiftUIView = swiftUIView(viewModel: viewModel(data: [Data, Data, Data]))
return UIHostingController(rootView: swiftUIView)
}
Then pushing it onto the UINavigationView
stack:
[self.navigationController pushViewController:hostingViewController animated:YES];
This gets us to SwiftUI
's environment. But, if our SwiftUI
environment has it's own navigation stack with NavigationView
and NavigationLink
, the original navigationBar
's back button can only navigate back to the original presenting UIViewController
.
Is there a way to push a SwiftUI
view embedded in a NavigationView
onto an existing UINavigationController
stack?
The only thought we've had so far is creating a new UIHostingViewController
for each new SwiftUI
screen, and pushing that onto the stack via some kind of delegate method.
What we're looking for is something like this:
UINavigationStack: [UIViewController -> UIViewController -> SwiftUIView -> SwiftUIView]
Where the back <
arrow in the navigationBar
will behave as expected.
Please let us know if we can clarify further!
Upvotes: 10
Views: 3540
Reputation: 185
I had a similar problem - I added a SwiftUI view with NavigationView to a UIKit NavigationController which lead to two layers of navigation bars when continuing navigation in the SwiftUI View: UIKit NavigationController -> MyListNavigationView(MyListView) -> DetailView.
Adding SwiftUI view to UIKit NavigationController:
let swiftUIView = MyListNavigationView(content: contentList)
let hostingViewController = UIHostingController(rootView: swiftUIView)
self.navigationController?.pushViewController(hostingViewController, animated: true)
My simplified SwiftUI views (did not validate if it compiles after simplifications):
struct MyListNavigationView: View {
@State var content: [String]
var body: some View {
NavigationView { //replace with Group {
MyListView(content: $content)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
NavigationLink {
DetailView(data: "New Data")
} label: {
Image(systemName: "plus")
}
}
}
}
.navigationViewStyle(.stack)
.navigationTitle("My Title")
}
}
struct MyListView: View {
@Binding var content: [String]
var body: some View {
List(content, id: \.self) { data in
NavigationLink(destination: DetailsView(data: data) {
MyRow(data: data)
}
}
}
}
struct MyRow: View {
let data: String
var body: some View {
Text(data)
}
}
struct DetailView: View {
let data: String
var body: some View {
Text(data)
}
}
So with that setup I had 2 layers of navigation bars - and with a simple change it all worked out for me:
As I only added MyListNavigationView
to a UIKit NavigationController, I did not need a standalone SwiftUI NavigationView
and just replaced it with a Group
- and all navigation/toolbar settings from my SwiftUI views have been adopted by the parent UIKit NavigationController and there was only one navigation bar.
Upvotes: 6