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()
}
}
SwiftUI 2 pop to root view with no Scene delegate
A possible solution is to create an ObservableObject
that is responsible for routing:
enum AppView {
case login, main
}
class ViewRouter: ObservableObject {
// here you can decide which view to show at launch
@Published var currentView: AppView = .login
}
Then, you can inject this ViewRouter
as an EnvironmentObject
to the root view:
@main
struct TestApp: App {
@StateObject private var viewRouter = ViewRouter()
var body: some Scene {
WindowGroup {
RootView()
.environmentObject(viewRouter)
}
}
}
Now you can change the current view from any view:
struct RootView: View {
@EnvironmentObject private var viewRouter: ViewRouter
var body: some View {
VStack {
if viewRouter.currentView == .login {
LoginView()
} else if viewRouter.currentView == .main {
MainView()
}
}
}
}
struct LoginView: View {
@EnvironmentObject private var viewRouter: ViewRouter
var body: some View {
VStack {
Text("Login View")
Button("Log in") {
viewRouter.currentView = .main
}
}
}
}
struct MainView: View {
@EnvironmentObject private var viewRouter: ViewRouter
var body: some View {
VStack {
Text("Main View")
Button("Log out") {
viewRouter.currentView = .login
}
}
}
}
SwiftUI ColorPicker cause pop to root view
NavigationView
in each tab instead of outside the TabView
Pop to root view using Tab Bar in SwiftUI
We can use tab bar selection binding to get the selected index. On this binding we can check if the tab is already selected then pop to root for navigation on selection.
struct ContentView: View {
@State var showingDetail = false
@State var selectedIndex:Int = 0
var selectionBinding: Binding<Int> { Binding(
get: {
self.selectedIndex
},
set: {
if $0 == self.selectedIndex && $0 == 0 && showingDetail {
print("Pop to root view for first tab!!")
showingDetail = false
}
self.selectedIndex = $0
}
)}
var body: some View {
TabView(selection:selectionBinding) {
NavigationView {
VStack {
Text("First View")
NavigationLink(destination: DetailView(), isActive: $showingDetail) {
Text("Go to detail")
}
}
}
.tabItem { Text("First") }.tag(0)
Text("Second View")
.tabItem { Text("Second") }.tag(1)
}
}
}
struct DetailView: View {
var body: some View {
Text("Detail")
}
}
Related Topics
Difference Between 'Let' and 'Var' in Swift
How to Create Instances of Managed Object Subclasses in a Nsmanagedobject Swift Extension
Biginteger Equivalent in Swift
How to Hash Nsstring With Sha1 in Swift
What Is a Good Example to Differentiate Between Fileprivate and Private in Swift3
Get Terminal Output After a Command Swift
Does Swift Copy on Write For All Structs
Swift - Validating Uitextfield
Swift - Sort Array of Objects With Multiple Criteria
How to Use Special Character in Nsurl
Realitykit VS Scenekit VS Metal - High-Quality Rendering
What Sorting Algorithm Does Swift Implement For Its Standard Library