Search code examples
swiftuinavigation

remove the current view and then navigate to another view in swiftui


Is there a way to remove the current view and then go to another view in swiftui?

i dont want to navigate to the third view right away, i need to remove the current view before navigating to the third view:

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            VStack {
              
                Text("1")

                NavigationLink(destination: Page2View()) {
                    Text("View Page 2")
                        .padding()
                        .background(Color.blue)
                        .foregroundColor(.white)
                        .cornerRadius(10)
                }
                .padding()

            
            }
            .navigationBarTitle("Main Page")
        }
    }
}

struct Page2View: View {
    var body: some View {
        Text("This is Page 2")
            .navigationBarTitle("Page 2")
    }
}

struct Page3View: View {
    var body: some View {
        Text("This is Page 3")
            .navigationBarTitle("Page 3")
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

i provided the simplest code to illustrate the issue


Solution

  • import SwiftUI
    
    enum Path: Hashable {
        case page2
        case page3
    }
    
    struct ContentView: View {
        @State var navigationPath = NavigationPath()
        
        var body: some View {
            NavigationStack(path: $navigationPath) {
                VStack {
                    
                    Text("1")
                    
                    Button(action: {
                        navigationPath.append(Path.page2)
                    }, label: {
                        Text("View Page 2")
                            .padding()
                            .background(Color.blue)
                            .foregroundColor(.white)
                            .cornerRadius(10)
                    })
                    .padding()
                    
                    
                }
                .navigationBarTitle("Main Page")
                .navigationDestination(for: Path.self) { path in
                    switch path {
                    case .page2: Page2View {
                        navigationPath.removeLast()
                        navigationPath.append(Path.page3)
                    }
                    case .page3: Page3View()
                    }
                }
            }
        }
    }
    
    struct Page2View: View {
        var onClick: () -> ()
        
        var body: some View {
            Text("This is Page 2")
                .navigationBarTitle("Page 2")
            
            Button("Go to Page 3") {
                onClick()
            }
        }
    }
    
    struct Page3View: View {
        var body: some View {
            Text("This is Page 3")
                .navigationBarTitle("Page 3")
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    

    This code should do it, here's a breakdown:

    • Enum Path: This enum defines the possible navigation destinations (page2 and page3).

    • @State var navigationPath: This state variable holds the current navigation stack. Using this allows us to programmatically control the navigation, such as adding, removing, or replacing views.

    • Navigation to Page 2: The Button in the main view appends Path.page2 to navigationPath, which results in navigation to Page2View. This is due to the .navigationDestination(for:path:) modifier that maps Path.page2 to Page2View.

    • Inside Page2View: This view takes a closure onClick as a parameter. This closure is for when the user wants to navigate from Page 2 to Page 3. Inside Page2View, there's a Button labeled "Go to Page 3" which, when tapped, will call the onClick closure.

    • Navigating to Page 3: The onClick closure passed to Page2View is defined in the main view's .navigationDestination(for:path:) modifier for Path.page2. This closure first removes the last entry from navigationPath (which corresponds to Page2View) and then appends Path.page3, thereby navigating to Page3View and removing Page2View from the stack.