Changing the Root View in SwiftUI
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 theLoginView
.
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 toHomeView
.
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 theLoginView
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