Is it possible in SwiftUI to come back to a specific view? Let's say I have three views this way:
struct View1: View {
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: View2()) {
Text("Navigate to View2")
}
.navigationBarTitle("View1")
}
}
}
}
struct View2: View {
var body: some View {
NavigationLink(destination: View3()) {
Text("Navigate to View3")
}
.navigationBarTitle("View2")
}
}
struct View3: View {
var body: some View {
Text("View3!")
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
View1()
}
}
#endif
The navigation works back and forth:
View1->View2->View3
View3->View2->View1
Is it possible to directly come back to View1
from the View3
? What I'm looking for is something similar to the UIKit
func popToViewController(_ viewController: UIViewController,
animated: Bool) -> [UIViewController]?
Trying to solve this issue I ended up creating an open source project called swiftui-navigation-stack
(https://github.com/biobeats/swiftui-navigation-stack). It contains the NavigationStackView
, a view that mimics all the navigation behaviours of the standard NavigationView
, adding some other features (all the features are explained in the readme of the repo). To answer the question here above we can use the NavigationStackView
this way:
Let's pretend we have to implement a navigation like this:
View1 (push)-> View2 (push)-> View3 (push)-> View4 (pop)-> View2
First of all embed your first view in a NavigationStackView
(as you'd do with the standard NavigationView
):
struct RootView: View {
var body: some View {
NavigationStackView {
View1()
}
}
}
Let's create these simple views to build the example:
struct View1: View {
var body: some View {
ZStack {
Color.yellow.edgesIgnoringSafeArea(.all)
VStack {
Text("VIEW 1")
Spacer()
PushView(destination: View2(), destinationId: "view2") {
Text("PUSH TO VIEW 2")
}
}
}
}
}
struct View2: View {
var body: some View {
ZStack {
Color.green.edgesIgnoringSafeArea(.all)
VStack {
Text("VIEW 2")
Spacer()
PushView(destination: View3()) {
Text("PUSH TO VIEW 3")
}
}
}
}
}
struct View3: View {
var body: some View {
ZStack {
Color.gray.edgesIgnoringSafeArea(.all)
VStack {
Text("VIEW 3")
Spacer()
PushView(destination: View4()) {
Text("PUSH TO VIEW 4")
}
}
}
}
}
struct View4: View {
var body: some View {
ZStack {
Color.white.edgesIgnoringSafeArea(.all)
VStack {
Text("VIEW 4")
Spacer()
PopView(destination: .view(withId: "view2")) {
Text("POP TO VIEW 2")
}
}
}
}
}
PushView
and PopView
let you navigate between views and, among other things, they let you specify an identifier for a view (so that you can come back to it if you need).
The following is the complete example, you can copy-paste it to xCode to try it yourself:
import SwiftUI
import NavigationStack
struct RootView: View {
var body: some View {
NavigationStackView {
View1()
}
}
}
struct View1: View {
var body: some View {
ZStack {
Color.yellow.edgesIgnoringSafeArea(.all)
VStack {
Text("VIEW 1")
Spacer()
PushView(destination: View2(), destinationId: "view2") {
Text("PUSH TO VIEW 2")
}
}
}
}
}
struct View2: View {
var body: some View {
ZStack {
Color.green.edgesIgnoringSafeArea(.all)
VStack {
Text("VIEW 2")
Spacer()
PushView(destination: View3()) {
Text("PUSH TO VIEW 3")
}
}
}
}
}
struct View3: View {
var body: some View {
ZStack {
Color.gray.edgesIgnoringSafeArea(.all)
VStack {
Text("VIEW 3")
Spacer()
PushView(destination: View4()) {
Text("PUSH TO VIEW 4")
}
}
}
}
}
struct View4: View {
var body: some View {
ZStack {
Color.white.edgesIgnoringSafeArea(.all)
VStack {
Text("VIEW 4")
Spacer()
PopView(destination: .view(withId: "view2")) {
Text("POP TO VIEW 2")
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
RootView()
}
}
The result is:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With