Search code examples
iosswiftswiftuidarkmode

How to set the preferred ColorScheme of an SwiftUI app


In my app I would like to have a section in the settings where the user can set whether he prefers light, dark or system. My question is simple but I can not find anything on the internet about it. How can I set the darkmode to these three values? I tried the following (example app, is working):

import SwiftUI

struct ContentView: View {
    @State private var systemDesign: ColorScheme = .light
    @State private var darkMode: Int = 0
    @Environment(\.colorScheme) var colorScheme
    
    private var preferredDesign: ColorScheme {
        print("preferredDesign used.")
        if darkMode == 1 {
            return .light
        } else if darkMode == 2 {
            return .dark
        } else {
            print("systemDesign is  \(systemDesign)")
            return systemDesign
        }
    }
    
    var body: some View {
        VStack {
            Form {
                HStack{
                    Text("Design")
                        .frame(maxWidth: 100, alignment: .leading)
                    Spacer()
                    GeometryReader { geometry in
                        Picker("Design Picker", selection: $darkMode) {
                            Text("System").tag(0)
                            Text("Hell").tag(1)
                            Text("Dunkel").tag(2)
                        }
                        .pickerStyle(SegmentedPickerStyle())
                        .frame(width: geometry.size.width)
                    }
                }
                .padding(.top, 13)
                .padding(.bottom, 13)
            }
            Divider()
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
        }
        .padding()
        .preferredColorScheme(preferredDesign)
        .onChange(of: colorScheme) { newColorScheme in
            print("ColorScheme has changed.")
            systemDesign = newColorScheme
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

So i have a Picker and set the value of preferredColorScheme to the value the computed Variable gives me for the specified value. when i toggle darkmode on the device the @State property should be set to the darkmode setting of the device. But this does not work properly. Has anyone an Idea how i can realize that?


Solution

  • The modifier preferredColorScheme takes an argument of ColorScheme?. Returning nil will tell the view that no specific color scheme should be used and defaults to the system's theme.

    So you don't need systemDesign anymore, and preferredDesign should now be:

    private var preferredDesign: ColorScheme? {
        print("preferredDesign used.")
        if darkMode == 1 {
            return .light
        } else if darkMode == 2 {
            return .dark
        } else {
            return nil
        }
    }