A lot of people recently asked us how to tell SwiftUI that a certain screen, for instance an onboarding view, should only be shown when the app launches the first time. To implement this functionality, follow the steps belowđ
Step 1: Make sure you already set up your onboarding view that should be shown when the app launches for the first time. We made a whole tutorial about creating a multi-paged one.
struct OnboardingView: View {
//Compose your Onboarding view, tutorial can be found here:
//https://blckbirds.com/post/how-to-create-a-onboarding-screen-in-swiftui-1/
}
Step 2: Next, make sure you created your home view that should be shown when the app has already launched before.â
struct HomeView: View {
//Compose your home view
}
Step 3: Next, we need to take control of when to show which view. For this purpose, we create an ObservableObject which serves as the ârouterâ for our SwiftUI appâs views. This is basically the same technique we use for navigating independently between several views in SwiftUI.
class ViewRouter: ObservableObject {
@Published var currentPage: String
}
Step 4: Next, we create the MotherView which holds both, our onboarding view and our default home view. Based on our ViewRouterâs currentPage property, we either load the onboarding or the home view.
struct MotherView : View {
@EnvironmentObject var viewRouter: ViewRouter
var body: some View {
VStack {
if viewRouter.currentPage == "onboardingView" {
OnboardingView()
} else if viewRouter.currentPage == "homeView" {
HomeView()
}
}
}
}
struct MotherView_Previews: PreviewProvider {
static var previews: some View {
MotherView().environmentObject(ViewRouter())
}
}
Step 5: In our SceneDelegate.swift file’s scene function, we set our MotherView as the root view when the app launches.â
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: MotherView().environmentObject(ViewRouter()))
self.window = window
window.makeKeyAndVisible()
}
}
Step 6: The trick now is to decide which view should be shown when the ViewRouter gets initialised (which is at the appâs launch!). For this purpose, we use UserDefaults. If there is already a key called âdidLaunchBeforeâ stored, we tell our ViewRouter to show the home view at the appâs launch. When no key can be found, we know that itâs the first time the app launches and we tell our ViewRouter to display the onboarding view. Then, we create such a key so that when launching the app the next time, the home view gets chosen instead.â
class ViewRouter: ObservableObject {
init() {
if !UserDefaults.standard.bool(forKey: "didLaunchBefore") {
UserDefaults.standard.set(true, forKey: "didLaunchBefore")
currentPage = "onboardingView"
} else {
currentPage = "homeView"
}
}
@Published var currentPage: String
}
And thatâs it! With this technique, you can tell your SwiftUI app to show the onboarding screen only when the app launches for the first time đĄ
Weâve uploaded the whole source code of this app to GitHub.
I hope you enjoyed this tutorial! If you want to learn more about SwiftUI, check out our other tutorials! Also make sure you follow us on Instagram and subscribe to our newsletter to not miss any updates, tutorials and tips about SwiftUI and more!
12 replies on “How to show a SwiftUI onboarding screen only when to app launches for the first time”
Great tutorial đđđ
It helps me a lot
Hello, thank you for another interesting tutorial! I am very curious, why would anyone build an app that only opens an initial screen one time only? Is there an actual logical reason to do this? i.e. if you missed the info on the initial screen you would have to delete and reinstall the app, correct?
How does one eliminate the stored key âdidLaunchBeforeâ so that it resets to initial values?
And what about a button to toggle between the two views via @EnvironmentObject?
Thx for any feedback!
Hello Richard, for instance, you can use this technique for creating an onboarding/tutorial screen that shows the user the app functionality when he launches the app for the first time. The didLaunchBefore key only “resets” after you delete and reinstall the app.
Great tutorial Blckbirds, thanks!!
Hello Richard, you can do at least 2 easy things to show the Onboarding views without deleting/reinstalling the app.
1) add a button in the HomeView calling a function that sets the value of the stored key âdidLaunchBeforeâ to ‘false’:
func resetOnboardingView() {
UserDefaults.standard.set(false, forKey: “didLaunchBefore”)
}
When you close the app and relaunch, it shows the onboarding views again.
2) or, since ViewRouter is an environmentObject, you can also bind to it in HomeView:
@EnvironmentObject var viewRouter: ViewRouter
Then add a button calling a function that will change the currentPage parameter of the viewRouter:
func showOnboardingView() {
viewRouter.currentPage = “onboardingView”
}
Hope this helps.
Cheers!
Thanks for your kind words and many thanks to your explanation!
Howdy! I see! Thanks for the feedback! After building several versions of a launch screen I realized the benefits and also discovered how to setup an animated display with a delay. All good stuff! I had never used launch screen prior. Thx again!
Thank you for a this tutorial, it’s just what I’m looking for but I’m struggling to use the code in the new App.swift file instead of SceneDelegate.swift, could you provide any help with this?
If I place the code which goes in SceneDelegate in the [AppName]App.swift file it has the problem: “Closure containing a declaration cannot be used with function builder ‘SceneBuilder'”
I would very much appreciate any thoughts you have.
Hi Nat, could you post your App struct code?
exactly what I was looking for, good stuff!
@BLKBIRDS now for testing purposes, is there an easy way to reset/delete the UserDefault so the onboardingView would show again?
Hi, great tutorial! I’m just curious where to put the scene function now that in SwiftUI 2.0 there is no SceneDelegate.swift anymore?
Thanks in advance!
Super helpful. Thank you!