preferredColorScheme not working with Xcode 16

In this app, I set the preferredColorScheme in main

@main
struct TheApp: App {
    @AppStorage("isDarkMode") private var isDarkMode = false   

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

isDarkMode is changed dynamically in code.

When code is compiled with Xcode 15.3, the background of ContentView changes from light to dark or vice versa.

When compiled with Xcode 16, no more change.

However, direct changes to objects do work, such as:

TextField("N", value: $t, format: .number)
          .frame(width: 40)
          .background(isDarkMode ? .gray : .white)  

What has changed in Xcode 16 ? Is it documented somewhere ?

I saw this SO thread which describe similar problem. https://www.reddit.com/r/swift/comments/upkprg/preferredcolorscheme_toggle_not_working/

I tried to change the colorScheme

To no avail. The View background remains unchanged but some subviews get changed… And anyway, that would not explain the difference between Xcode 15 and 16…

Tested in Xcode 16.1ß1 without success.

Hi @Claude31 ,

Can you try again with the latest Xcode? (beta 3) - https://developer.apple.com/download/applications/

Also, are you able to try with macOS 15.1? This is a Mac app, right?

I tried with 16.1ß3, same issues.

However, if I set the background manually on a view (with colors that mimic the preferredScheme), it works:

.background(isDarkMode ? Color.veryDarkGray : `Color.lightGray)`

But having to do it on any subview is not a viable solution.

So for the time being I stay with 15.3, but that's not a sustainable option either.

Could it be a compatibility issue between Xcode 16.x and MacOS 14.y ?

 

Also, are you able to try with macOS 15.1? This is a Mac app, right?

  • I cannot try with MacOS 15 at this time.
  • And in any case, app has to run on versions below (down to MacOS 12 in fact), so that would not solve the problem.
  • The app (SwiftUI) runs on MacOS and iOS

I also tested the app by setting the Mac to dark mode. App does not adapt to dark.

So it is just as if, with Xcode 16, preferredColorScheme was ignored.

Could it come from AppStorage (but once again, it worked in Xcode 15).

I created a minimal project in Xcode 15.3 to reproduce the issue (run on MacOS 14.7).

When compiled with Xcode 15.3, the toggle switches from light to dark mode. When compiled with Xcode 16 (16.0 or 16.1ß3), the toggle has no effect.

I attached the complete project to FB report.

import SwiftUI

@main
struct DarkModeTest_MacApp: App {
    @AppStorage("isDarkMode") private var isDarkMode = false

    var body: some Scene {
        WindowGroup {
            ContentView()
                .frame(
                    minWidth: 300, maxWidth: .infinity,
                    minHeight: 200, maxHeight: .infinity)
                .preferredColorScheme(isDarkMode ? .dark : .light)
        }
        .windowResizability(.contentSize)
    }
}
import SwiftUI

struct ContentView: View {
    @AppStorage("isDarkMode") private var isDarkMode = false

    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")

            Button(action: {
                isDarkMode.toggle()
            }) {
                Text("Toggle")
            }
        }
        .padding()
    }
}

#Preview {
    ContentView()
}

Additional information: It works on iPad (simulator).

Hi @Claude31 , If could help, I tried to make a sample app project and insert the code you attached. Run on Mac OS 15.0.1, with Xcode Version 16.0 (16A242d), and toggle work as expected. attached screenshot

It could be an incompatibility with versions of Mac OS minor than 15.

Bye Rob

@GRALInfo, thanks for the test and the information.

Effectively that could be an incompatibility with MacOS < 15. Which nevertheless is an issue, if we cannot keep the apps running correctly on not so older OS versions.

To fully assess the point, would you have the opportunity to test the app produced by Xcode 16 on an older OS ?

I'll post the answer if I get from FB.

Hi @Claude31 , I've just make a debug session on Mac OS Sonoma (14.6) and same project seems doesn't work. Toogle change isDarkMode property correctly, but SwiftUI rendering view is not raised on ContentView.

It seems that binding on AppStorage variable is not raised. Note that after close and reopening app , value are read correctly from ContentView.

Strange behaviour.

Anyway, take this as suggestion, I should not use @AppStorage in this way. Probably using a custom init on ContentView with a data binding property that is propagated on ContentView itself could resolve this issue.

Bye Rob

Thanks for the test @GRALInfo !

@Claude31 due to the info that both you and @GRALInfo have provided, it seems like this is a known issue that has been fixed in macOS 15. Since you cannot update, could you try putting the User Defaults value into an observable class and manually writing a getter and setter and see if that works?

I saw some folks chatting about this here: https://github.com/sindresorhus/Settings/issues/117, maybe check that out.

@GRALInfo Thanks for this additional testing.

Using AppStorage (for a simple Bool) was an early design decision as the property isDarkMode is used in many views.

So I could effectively use an environment variable and initialise in .onAppear or in an init().

I'll go this way if the bug is not corrected (I now definitely think it is an Xcode 16 regression).

But falling on such issues in development environment is making me a bit nervous, wondering what else may be broken ?

@VisionPro Thanks for the link.

It is another way of doing it, but that denies the simplicity of AppStorage. If it is not corrected in a future Xcode release, does it mean that AppStorage is on obsolescence path ?

@Vision Pro engineer

So, would this statement be correct ?

To work properly, SwiftUI with Xcode 16 requires at least macOS 15

If so, it should be in the release notes, at least as a known issue.

preferredColorScheme not working with Xcode 16
 
 
Q