user15307343
user15307343

Reputation:

Why I am not success to do onboarding screen only when to app launches for the first time in SwiftUI?

I am new in SwiftUI, I have Onboarding screen in my app, and it is work, but I want to see this Onboarding screen only one times, and I used ViewRouter class for it, my project work, but I am still not success to do it, where I missed?

ViewRouter:

class ViewRouter: ObservableObject {
    @Published var onboardinDone = "onboardingView"

    init() {
        if !UserDefaults.standard.bool(forKey: "didLaunchBefore") {
            UserDefaults.standard.set(true, forKey: "didLaunchBefore")
            onboardinDone = "onboardingView"
        } else {
            onboardinDone = "initialView"
        }
    }
}

ContentView:

    struct ContentView: View {

    @State private var onboardinDone = false
      var data = OnboardingData.data

    
    var body: some View {
        Group {
            
            if !onboardinDone {
                OnboardingView(data: data, doneFunction: {
               
                    self.onboardinDone = true
             
                })
            } else {
                ScreenView()
            }
        }
      }
    }

Upvotes: 0

Views: 229

Answers (1)

jnpdx
jnpdx

Reputation: 52312

You aren't using your ViewRouter in the code you've shown at all right now.

The easiest change would be to use @AppStorage instead of @State in your view, which will persist across launches. You can even use the same key you were using in your ViewRouter:

struct ContentView: View {
    
    @AppStorage("didLaunchBefore") private var onboardingDone = false
    var data = OnboardingData.data
    
    var body: some View {
        Group {
            
            if !onboardingDone {
                OnboardingView(data: data, doneFunction: {
                    self.onboardingDone = true
                })
            } else {
                ScreenView()
            }
        }
    }
}

struct OnboardingView : View {
    var data : String
    var doneFunction: () -> Void
    
    var body: some View {
        Text("onboarding")
        Button("Done") {
            self.doneFunction()
        }
    }
}

If you did want to use the ViewRouter, here's another alternative:

class ViewRouter: ObservableObject {
    @Published var route : Routes = .initial
    @AppStorage("didLaunchBefore") private var didLaunchBefore = false

    enum Routes {
        case initial, onboarding
    }
    
    init() {
        if !didLaunchBefore {
            didLaunchBefore = true
            route = .onboarding
        } else {
            route = .initial
        }
    }
    
    func finishOnboarding() {
        didLaunchBefore = true
        route = .initial
    }
}

struct ContentView: View {
    @StateObject private var viewRouter = ViewRouter()
    var data = OnboardingData.data
    
    var body: some View {
        Group {
            
            switch viewRouter.route {
            case .initial:
                ScreenView()
            case .onboarding:
                OnboardingView(data: data, doneFunction: {
                    viewRouter.finishOnboarding()
                })
            }
        }
    }
}

struct OnboardingView : View {
    var data : String
    var doneFunction: () -> Void
    
    var body: some View {
        Text("onboarding")
        Button("Done") {
            self.doneFunction()
        }
    }
}

Upvotes: 1

Related Questions