2

I'm using a toggle and @AppStorage to change the preferredColorScheme in my app. Dark mode and light mode works fine on Views other than sheets and full screen modals.

struct MyApp: App {

    @AppStorage("darkMode") var darkMode = false

    init() {
        FirebaseApp.configure()
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
                .preferredColorScheme(darkMode ? .dark : .light)
        }
    }
}

App Settings View:

struct AppSettingsView: View {

    @ObservedObject var appSettingsVM: AppSettingsViewModel

    var body: some View {
        ScrollView {
            Toggle("Dark Mode", isOn: $appSettingsVM.darkMode.animation())
                .toggleStyle(SwitchToggleStyle(tint: .orange))
                .padding()
        }
    }
}

App Settings View Model:

class AppSettingsViewModel: ObservableObject {

    @AppStorage("darkMode") var darkMode: Bool = false

}

There are multiple sheets and full screen modals under the Content View hierarchy and none of them respond to the changes in Color Scheme.

1

2 Answers 2

2

If you want to change the color scheme for full app, do not use preferredColorScheme(.dark) use environment instead

        NavigationView {
            //your code
        }.environment(\.colorScheme, .dark)

this will affect all the child views of the NavigationView

Sign up to request clarification or add additional context in comments.

1 Comment

Using preferredColorScheme works but thanks for the tip.
1

I modified the solution from a YouTube video and this works.

import Foundation
import UIKit

class ThemeManager {
    static let shared = ThemeManager()

    private init () {}

    func handleTheme(darkMode: Bool, system: Bool) {
    
        guard !system else {
            UIApplication.shared.windows.first?.overrideUserInterfaceStyle = .unspecified
            return
        }
        UIApplication.shared.windows.first?.overrideUserInterfaceStyle = darkMode ? .dark : .light
    }

}

import SwiftUI
import Firebase

@main
struct MyApp: App {

    @AppStorage("darkMode") var darkMode: Bool = false
    @AppStorage("system") var system: Bool = true

    init() {
        FirebaseApp.configure()
    }

    var body: some Scene {
        WindowGroup {
            MainView(mainVM: MainViewModel())
                .onAppear {
                    ThemeManager.shared.handleTheme(darkMode: self.darkMode, system: self.system)
                }
        }
    }

struct AppSettingsView: View {

    @ObservedObject var appSettingsVM: AppSettingsViewModel

    var body: some View {
    
        VStack {
        
            HStack {
            
                Text("App Settings")
                    .font(.title2)
                    .padding()
                Spacer()
            
            }
            .padding(.horizontal)
        
            Divider()
        
            ScrollView {
            
                HStack {
                
                    Text("Theme")
                
                    Spacer()
            
                    Menu {
                        Button("System") {
                            appSettingsVM.handleTheme(darkMode: false, system: true)
                        }
                        Button("Light") {
                            appSettingsVM.handleTheme(darkMode: false, system: false)
                        }
                        Button("Dark") {
                            appSettingsVM.handleTheme(darkMode: true, system: false)
                        }
                    } label: {
                        Text(appSettingsVM.darkModeLabel)
                            .frame(width: 80)
                            .padding(5)
                            .background(Color.orange)
                            .foregroundColor(.white)
                            .clipShape(RoundedRectangle(cornerRadius: 12))
                    }
                
                }
                .padding()
            }
        }

import SwiftUI

class AppSettingsViewModel: ObservableObject {

    @AppStorage("darkMode") var darkMode: Bool = false
    @AppStorage("system") var system: Bool = true
    @Published var darkModeLabel = "System"

    func handleTheme(darkMode: Bool, system: Bool) {
        self.darkMode = darkMode
        self.system = system
        if darkMode == false && system == true {
            withAnimation {
                self.darkModeLabel = "System"
            }
        } else if darkMode == false && system == false {
            withAnimation {
                self.darkModeLabel = "Light"
            }
        } else {
            withAnimation {
                self.darkModeLabel = "Dark"
            }
        }
        ThemeManager.shared.handleTheme(darkMode: self.darkMode, system: self.system)
    }
    
}

Video link: https://www.youtube.com/watch?v=j7a4jvHz4MM

1 Comment

Nice, btw to optimize and short a lil bit the code you could check the conditions like this : ``` withAnimation { if !darkMode { self.darkModeLabel = system ? "System" : "Light" } else { self.darkModeLabel = "Dark" } } ```

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.