Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I unwind to the MainView in SwiftUI

I can't find a way to go to the ContentView from ViewB without showing a secound NavigationView on top of the other NavigationView.

struct ContentView: View {
    var body: some View {
        NavigationView{
            VStack {
                Text("Go to ViewA")
                NavigationLink(destination: ViewA()) {Text("Go")}
            }.navigationBarTitle("ContentView")
        }
    }
}

struct ViewA: View {
   @Environment(\.presentationMode) var presentationMode
    var body: some View {
        VStack {
            Text("Go to ViewB")
            NavigationLink(destination: ViewB()) {Text("Go to B")}
            Text("Go back")
            Button(action: { self.presentationMode.wrappedValue.dismiss() }) {Text("Go to ContentView")}
        }.navigationBarTitle("ViewA")
    }
}

struct ViewB: View {
    @Environment(\.presentationMode) var presentationMode
    var body: some View {
        VStack {
            Text("Go Home")
            NavigationLink(destination: ContentView()) {Text("Go")}
            Text("Go back")
            Button(action: { self.presentationMode.wrappedValue.dismiss() }) {Text("Go to ViewB")}
        }.navigationBarTitle("ViewB")
    }
}

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

In the "old" Swift i could easily make an unwindSegue like

@IBAction func unwindToVCMain(segue:UIStoryboardSegue) { }
}

and easily call it like

performSegue(withIdentifier: "unwindToVcMain", sender: nil)

enter image description here

like image 720
crashboy Avatar asked Dec 25 '19 15:12

crashboy


People also ask

How do you make unwind segue in Swift?

Connect a Triggering Object to the Exit Control In your storyboard, create an unwind segue by right-clicking a triggering object and dragging to the Exit control at the top of your view controller's scene.

How do I navigate in SwiftUI?

SwiftUI's NavigationLink has a second initializer that has an isActive parameter, allowing us to read or write whether the navigation link is currently active. In practical terms, this means we can programmatically trigger the activation of a navigation link by setting whatever state it's watching to true.


1 Answers

Using the Swiftui NavigationLink

First, embed your first view in a navigation controller.

Then you insert a navigation link to the next view. The NavigationLink has different initialisers. Choose this one with the isActive parameter:

ScreenshotNavLink

It is a bit mind-bending at first, but the isActive parameter in the NavigationLink becomes true when the link is clicked and the navigation moves to the next screen.

It creates an instance that presents a destination when active

If I pass a binding keeping track of the state of this property, if at any time in my subsequent chain of views I set it to false again, it will reset and return to the original screen! It is quite neat!!

See this short example in code:

struct ContentView: View {
    @State private var isActive: Bool = false

    var body: some View {
        NavigationView {
            NavigationLink(
                destination: SecondView(isActive: $isActive),
                isActive: $isActive,
                label: {
                    Text("Go to second View")
                })
                .navigationTitle("MainView")
        }
    }
}

My second View:

struct SecondView: View {
    @Binding var isActive: Bool

    var body: some View {
            NavigationLink("Go to Third View",destination:  ThirdView(isActive: $isActive))
                .navigationTitle("Second View")
    }
}

And here the button to unwind, but it could be in any view. Setting isActive = false does some magic here!

struct ThirdView: View {
    @Binding var isActive: Bool

    var body: some View {
        Button("Unwind!"){
            isActive = false
        }
        .navigationTitle("Last View!")
    }
}
like image 178
multitudes Avatar answered Oct 18 '22 16:10

multitudes