Changing the Root View in SwiftUI

Jaykar Parmar
3 min readSep 2, 2023

--

Introduction: In SwiftUI, the ability to change the root view of your app dynamically can be a powerful feature, allowing you to tailor the user experience based on various conditions or user interactions. This guide will walk you through the process of changing the root view of your SwiftUI app, providing a step-by-step explanation and a complete code example.

import SwiftUI

@main
struct YourApp: App {
// You can change the root view by modifying the body property
var body: some Scene {
WindowGroup {
ContentView() // This is the root view by default
}
}
}

In the code above, ContentView is the default root view defined within the WindowGroup. To change the root view, you can replace ContentView with YourView or any other SwiftUI view you want to use as the new root view.

Now, Lets say we want to replace our view from any view, so how to do that? Let's take an example.

Creating an AppRootManager:

To begin, let’s set up a class called AppRootManager, which will serve as our central control for managing the app's root view. This class will be of type ObservableObject, allowing us to publish changes to its properties and trigger updates in our views.

import Foundation

final class AppRootManager: ObservableObject {

@Published var currentRoot: eAppRoots = .splash

enum eAppRoots {
case splash
case authentication
case home
}
}

In this code snippet, we’ve defined three possible root views: splash, authentication, and home. By default, we set the currentRoot to splash as we want to start our app with the SplashView.

Setting up the Main App:

Now, let’s configure our main app structure. We create a SwiftUI app using the @main attribute, and within it, we define an @StateObject for our AppRootManager to make it accessible throughout the entire app.

import SwiftUI

@main
struct SwiftUIChangeRootViewApp: App {

@StateObject private var appRootManager = AppRootManager()

var body: some Scene {
WindowGroup {
Group {
switch appRootManager.currentRoot {
case .splash:
SplashView()

case .authentication:
LoginView()

case .home:
HomeView()
}
}
.environmentObject(appRootManager)
}
}
}

In this structure, the appRootManager is instantiated as an @StateObject, and it's passed as an environmentObject to make it accessible within all the views.

Creating the Views:

Now, let’s define our views. We have three views: SplashView, LoginView, and HomeView. Each view reads the currentRoot property from the AppRootManager and reacts accordingly to change the root view.

  • SplashView: This is the initial view shown when the app launches. After a delay of 3 seconds, it transitions to the LoginView.
import SwiftUI

struct SplashView: View {

@EnvironmentObject private var appRootManager: AppRootManager

var body: some View {
ZStack {
Color.blue
.ignoresSafeArea()

Text("SwiftUI Change Root View")
.font(.title)
.fontWeight(.semibold)
.foregroundColor(.white)
}

.onAppear() {
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
withAnimation(.spring()) {
appRootManager.currentRoot = .authentication
}
}
}
}
}
  • LoginView: This view displays a login button. When the button is pressed, it triggers a root view change to HomeView.
import SwiftUI

struct LoginView: View {

@EnvironmentObject private var appRootManager: AppRootManager

var body: some View {
ZStack {
Color.pink
.ignoresSafeArea()

Button {
withAnimation(.spring()) {
appRootManager.currentRoot = .home
}
} label: {
Text("Login")
.fontWeight(.semibold)
.foregroundColor(.white)
.frame(maxWidth: .infinity)
.padding()
}
.background(.blue)
.cornerRadius(12)
.padding()
}
}
}
  • HomeView: This view represents the home screen. It provides an option to return to the LoginView by tapping a button.
import SwiftUI

struct HomeView: View {

@EnvironmentObject private var appRootManager: AppRootManager

var body: some View {
ZStack {
Color.orange
.ignoresSafeArea()

VStack(alignment: .trailing) {
HStack {
Spacer()
Button {
appRootManager.currentRoot = .authentication
} label: {
Image(systemName: "square.and.arrow.up")
.foregroundColor(.white)
.fontWeight(.semibold)
}
}
Spacer()
}
.padding(.trailing)

Text("Welcome Home")
.font(.title)
.fontWeight(.semibold)
.foregroundColor(.white)
}
}
}

Conclusion:

In this guide, we’ve explored how to dynamically change the root view in SwiftUI using an AppRootManager and @EnvironmentObject. This approach empowers you to create flexible and interactive user interfaces tailored to your app's requirements. By following these steps and using the provided code example, you can implement root view changes in your SwiftUI app with ease.

For a complete code example and to explore this concept further, you can find the code on GitHub: https://github.com/jaykarparmar/SwiftUIChangeRootView

--

--