iOS Swiftui: Pop or Dismiss View Programmatically

iOS SwiftUI: pop or dismiss view programmatically

This example uses the new environment var documented in the Beta 5 Release Notes, which was using a value property. It was changed in a later beta to use a wrappedValue property. This example is now current for the GM version. This exact same concept works to dismiss Modal views presented with the .sheet modifier.

import SwiftUI

struct DetailView: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
Button(
"Here is Detail View. Tap to go back.",
action: { self.presentationMode.wrappedValue.dismiss() }
)
}
}

struct RootView: View {
var body: some View {
VStack {
NavigationLink(destination: DetailView())
{ Text("I am Root. Tap for Detail View.") }
}
}
}

struct ContentView: View {
var body: some View {
NavigationView {
RootView()
}
}
}

Dismiss of SwiftUI Views one after the other programmatically does not work

Add .isDetailLink(false) to each NavigationLink in your views... and all works.

demo


NavigationLink(
destination: View2(types: ["Exams"], presentView2: $presentView2),
isActive: $presentView2,
label: {
Text("View2")
}).isDetailLink(false)

...

NavigationLink("View3", destination: View3(presentView3: $presentView3), isActive: $presentView3)
.isDetailLink(false)


...

NavigationLink("View4", destination: View4(presentView4: $presentView4), isActive: $presentView4)
.isDetailLink(false)

How to dismiss a SwiftUI NavigationView from a parent view

Here is the solution:

struct SwiftUIView: View {
@State var isPresent = true
@State var isDismissed: Bool = false

var body: some View {
HStack {
Button(action: {
isDismissed = true
}) {
Text("Dismiss View")
} // assume this button is always visible

NavigationView {
VStack {
Text("This is the NavigationView")
NavigationLink {
ViewToDismiss(dismissView: $isDismissed)
} label: {
Text("Go to view I want to exit")
}
}
}

}
}
}

struct ViewToDismiss: View {
@Environment(\.dismiss) private var dismiss
@Binding var dismissView: Bool
var body: some View {
Text("This is the view I want to exit")
.onChange(of: dismissView,
perform:
( { newValue in
dismiss()
}))
}
}

How can I pop to the Root view using SwiftUI?

Setting the view modifier isDetailLink to false on a NavigationLink is the key to getting pop-to-root to work. isDetailLink is true by default and is adaptive to the containing View. On iPad landscape for example, a Split view is separated and isDetailLink ensures the destination view will be shown on the right-hand side. Setting isDetailLink to false consequently means that the destination view will always be pushed onto the navigation stack; thus can always be popped off.

Along with setting isDetailLink to false on NavigationLink, pass the isActive binding to each subsequent destination view. At last when you want to pop to the root view, set the value to false and it will automatically pop everything off:

import SwiftUI

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

var body: some View {
NavigationView {
NavigationLink(
destination: ContentView2(rootIsActive: self.$isActive),
isActive: self.$isActive
) {
Text("Hello, World!")
}
.isDetailLink(false)
.navigationBarTitle("Root")
}
}
}

struct ContentView2: View {
@Binding var rootIsActive : Bool

var body: some View {
NavigationLink(destination: ContentView3(shouldPopToRootView: self.$rootIsActive)) {
Text("Hello, World #2!")
}
.isDetailLink(false)
.navigationBarTitle("Two")
}
}

struct ContentView3: View {
@Binding var shouldPopToRootView : Bool

var body: some View {
VStack {
Text("Hello, World #3!")
Button (action: { self.shouldPopToRootView = false } ){
Text("Pop to root")
}
}.navigationBarTitle("Three")
}
}

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

Screen capture



Related Topics



Leave a reply



Submit