简体   繁体   中英

SwiftUI: Change view and remove parent

I have a View with a NavigationLink . This NavigationLink is a 'logout' button, so when the user clicks this, I don't want them to be able to click the "Back" button in the NavigationBar . Is there a way to programmatically change view, and remove the "parent" view.

Here is the view with logout button:

struct SettingsView: View {

    @State private var didLogout: Bool = false
    
    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(destination: Login(), isActive: $didLogout) {
                    Button(action: {
                        //logout code here
                        self.didLogout = true
                    }) {
                        Text("Logout")
                    }
                }
            }
        }
    }
}

Here is the login view (the view I am pushing to when user logs out):

struct Login: View {
    
    //Login states
    @State var isActive = false
    @State var attemptingLogin = false
    @State var didLoginFail = false
    
    var body: some View {
        
        NavigationView {
            VStack {
                if (attemptingLogin == true) {
                    ProgressView()
                        .progressViewStyle(CircularProgressViewStyle())
                }
                
                NavigationLink(destination: blah(), isActive: $isActive) {
                    Button(action: {
                        attemptingLogin = true
                        blah.Login() { didLogin in
                            if didLogin == true {
                                self.isActive = true
                            } else {
                                self.isActive = false
                                self.didLoginFail = true
                                self.attemptingLogin = false
                            }
                        }
                    }) {
                        Text("Login")
                    }
                }        
            }.padding()
        }
    }
}

I've removed a few bits of code that aren't required for the question. Any help would be greatly appreciated, as I can't find anything online for this issue. I feel like I'm just not wording my queries correctly, as I'm sure many have run into this issue before with SwiftUI.

Like I said, if there is a way to "forget" the history of the NavigationView, and treat this as the top view in the stack?

There are various questions and answers here on SO about "pop to top" or "pop to root", which may be what you're looking for:

However, another common pattern is to conditionally display your NavigationView depending on if you're logged in or not. That might look like this:

class StateManager : ObservableObject {
    @Published private(set) var isLoggedIn = false
    
    func changeLogin(state: Bool) {
        withAnimation {
            isLoggedIn = state
        }
    }
}

struct ContentView: View {
    @StateObject var stateManager = StateManager()
    
    var body: some View {
        if stateManager.isLoggedIn {
            LoggedInView(stateManager: stateManager)
                .transition(.slide)
        } else {
            LoginView(stateManager: stateManager)
                .transition(.slide)
        }
    }
}

struct LoginView : View {
    @ObservedObject var stateManager : StateManager
    
    var body: some View {
        Button("Log in") {
            stateManager.changeLogin(state: true)
        }
    }
}

struct LoggedInView : View {
    @ObservedObject var stateManager : StateManager
    
    var body: some View {
        NavigationView {
            Button("Log out") {
                stateManager.changeLogin(state: false)
            }.navigationBarTitle("Logged in")
        }
    }
}

what i have seen so far, this is not a good practice, usually a good logical storyboard design starts with a splash screen and then gets replaced by login or signup screen when you enter the app you push to either tab bar or sidebar screen which is your main menu or root menu and each of their items are embedded in a navigationView to push to internal views and pop from them to go back. it would be better if you don't hide and show navigationView.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM