Home > OS >  Show new view and completely destroy old view when clicking on Text
Show new view and completely destroy old view when clicking on Text

Time:10-19

So I have been wanting to do this for some time, but I can't figure out how to approach this, so I'm reaching out to see if someone might be able to help me.

So let's say that I have the following code, which when the app loads, loads the "MainView":

struct MapGlider: App {
    @ObservedObject var mainViewModel = MainViewModel()
    var body: some Scene {
        WindowGroup {
            MainView()
                .environmentObject(mainViewModel)
        }
    }
}

This loads the map as soon as the app is opened, which is great! All works great there.

Now I will be switching that out to show the OnboardingView() when the app loads such as:

struct MapGlider: App {
    @ObservedObject var mainViewModel = MainViewModel()
    var body: some Scene {
        WindowGroup {
            OnboardingView()
        }
    }
}

Now, I have a OnboardingView that shows a ZStack with some options, as show in this code below:

struct OnboardingView: View {
    @State private var showGetStartedSheet = false
    @ObservedObject var mainViewModel = MainViewModel()
    var body: some View {
        if #available(iOS 16.0, *) {
            NavigationStack {
                ZStack(alignment: .top) {
                    VStack {
                        LazyVGrid(columns: [GridItem(), GridItem(), GridItem(alignment: .topTrailing)], content: {
                            Spacer()
                            Image("onboarding-logo")
                                .border(.red)
                            
                            NavigationLink(destination: MainView().environmentObject(mainViewModel), label: {
                                Text("Skip")
                            })
                        })
                        .border(.red)
                    }
                }
                .border(.blue)
            }
        } else {
            // Fallback on earlier versions
        }
    }
}

Which outputs the following:
enter image description here

What I'm trying to achieve:

  • When someone clicks on the "Skip" text, to kill the OnboardingView and show the MainView().
  • The closest I got is setting a NavigationLink, but that had a back button and doesn't work so well, I want to be able to go to the MainView and not be able to go back to OnboardingView.

All help will be appreciated!

CodePudding user response:

You could use a container view that conditionally displays the onboarding or main views, depending on the state of a variable (stored at the parent level). That variable can be passed down via a Binding:

Simplified example that should be easily applicable to your code:

class AppState: ObservableObject {
    @Published var showOnboarding = true
}

@main
struct CustomCardViewApp: App {
    @StateObject var appState = AppState()
    
    var body: some Scene {
        WindowGroup {
            MainScreenContainer(showOnboarding: $appState.showOnboarding)
        }
    }
}

struct MainScreenContainer: View {
    @Binding var showOnboarding: Bool
    
    var body: some View {
        if showOnboarding {
            OnboardingView(showOnboarding: $showOnboarding)
        } else {
            MainView()
        }
    }
}

struct OnboardingView: View {
    @Binding var showOnboarding: Bool
    
    var body: some View {
        Text("Onboarding")
        Button("Skip") {
            showOnboarding = false
        }
    }
}

struct MainView: View {
    var body: some View {
        Text("Main")
    }
}

  • Related