How can I change root view in SwiftUI (without UIHostingController)?

47 views Asked by At

How can I organize my code in project, so I can easily change Root View from every place of my app?

Is it possible to do it inside @main struct MyApp: App { ... } or I need to create additional intermediate RootView struct?

1

There are 1 answers

0
IBAction On BEST ANSWER

Found a solution without any additional stuff(e.g. RootView struct). I have here example project with 3 screens, all of them can switch rootView from App struct via NavigationManager.

Main App struct:

@main
struct SwiftUI_TestApp: App {
    
    @StateObject var navigationManager: NavigationManager
    
    init() {
        _navigationManager = StateObject(wrappedValue: NavigationManager(rootScreen: .main))
    }
    
    var body: some Scene {
        WindowGroup {
            switch navigationManager.rootScreen {
            case .content:
                ContentView()
                    .environmentObject(navigationManager)
            case .main:
                MainView()
                    .environmentObject(navigationManager)
            case .settings:
                SettingsView()
                    .environmentObject(navigationManager)
            }
        }
    }
}

NavigationManager class:

final class NavigationManager: ObservableObject {
    
    enum Screen: Hashable {
        case main
        case content
        case settings
    }
    
    @Published var rootScreen: Screen
    
    init(rootScreen: Screen) {
        self.rootScreen = rootScreen
    }
}

ContentView struct:

struct ContentView: View {
    
    @EnvironmentObject var navigationManager: NavigationManager
    
    var body: some View {
        VStack {
            Text("Content")
            
            Button {
                navigationManager.rootScreen = .main
            } label: {
                Text("Show Main")
            }
            
            Button {
                navigationManager.rootScreen = .settings
            } label: {
                Text("Show Settings")
            }
        }
    }
}

MainView struct:

struct MainView: View {
    
    @EnvironmentObject var navigationManager: NavigationManager
    
    var body: some View {
        VStack {
            Text("Main")
            
            Button {
                navigationManager.rootScreen = .content
            } label: {
                Text("Show Content")
            }
            
            Button {
                navigationManager.rootScreen = .settings
            } label: {
                Text("Show Settings")
            }
        }
    }
}

SettingsView struct:

struct SettingsView: View {
    
    @EnvironmentObject var navigationManager: NavigationManager
    
    var body: some View {
        VStack {
            Text("Settings")
            
            Button {
                navigationManager.rootScreen = .content
            } label: {
                Text("Show Content")
            }
            
            Button {
                navigationManager.rootScreen = .main
            } label: {
                Text("Show Main")
            }
        }
    }
}