Skip to content

Instantly share code, notes, and snippets.

@chockenberry
Created September 11, 2024 18:36
Show Gist options
  • Save chockenberry/a2a23a12604e333b1c2a8b71e7a24155 to your computer and use it in GitHub Desktop.
Save chockenberry/a2a23a12604e333b1c2a8b71e7a24155 to your computer and use it in GitHub Desktop.
//
// ColorSchemeApp.swift
// ColorScheme
//
// Created by Craig Hockenberry on 9/11/24.
//
import SwiftUI
@main
struct ColorSchemeApp: App {
@AppStorage("preferredColorScheme") private var preferredColorScheme: ColorScheme?
var body: some Scene {
WindowGroup {
ContentView()
.preferredColorScheme(preferredColorScheme)
}
.onChange(of: preferredColorScheme) { oldValue, newValue in
print("ColorSchemeApp: preferredColorScheme: \(oldValue) -> \(newValue)")
}
}
}
// NOTE: This allows @AppStorage to store an optional ColorScheme
extension ColorScheme: RawRepresentable {
public init?(rawValue: Int) {
guard let userInterfaceStyle = UIUserInterfaceStyle(rawValue: rawValue),
userInterfaceStyle != .unspecified,
let colorScheme = ColorScheme(userInterfaceStyle)
else {
//print("ColorScheme init: colorScheme = nil, rawValue = \(rawValue)")
return nil
}
//print("ColorScheme init: colorScheme = \(colorScheme), userInterfaceStyle = \(userInterfaceStyle)")
self = colorScheme
}
public var rawValue: Int {
let userInterfaceStyle = UIUserInterfaceStyle(self)
//print("ColorScheme rawValue: self = \(self), userInterfaceStyle = \(userInterfaceStyle)")
return userInterfaceStyle.rawValue
}
}
// NOTE: This provides a display name for an optional ColorScheme
extension ColorScheme? {
public var displayName: String {
if let self {
switch self {
case .dark: return "Dark"
case .light: return "Light"
@unknown default:
return "Unknown"
}
}
else {
return "System"
}
}
}
struct ContentView: View {
@State private var presentSettings = false
@State private var identityHack: Int = 0
@AppStorage("preferredColorScheme") private var preferredColorScheme: ColorScheme?
var body: some View {
VStack(spacing: 40) {
Text(preferredColorScheme.displayName).font(.headline)
Button("Show Settings") {
presentSettings = true
}
}
.padding()
.sheet(isPresented: $presentSettings) {
SettingsView()
.id(identityHack) // an attempt to force an update by changing structural identity
.preferredColorScheme(preferredColorScheme)
.onChange(of: identityHack) { oldValue, newValue in
print("SettingView: identityHack: \(oldValue) -> \(newValue)")
}
}
.onChange(of: preferredColorScheme) { oldValue, newValue in
print("ContentView: preferredColorScheme: \(oldValue) -> \(newValue)")
identityHack += 1
}
}
}
struct SettingsView: View {
@Environment(\.dismiss) private var dismiss
@State private var path = NavigationPath()
@AppStorage("preferredColorScheme") private var preferredColorScheme: ColorScheme?
var body: some View {
NavigationStack(path: $path) {
Form {
Section {
Picker("Theme", selection: $preferredColorScheme) {
Text("System").tag(nil as ColorScheme?)
Text("Dark").tag(ColorScheme.dark as ColorScheme?)
Text("Light").tag(ColorScheme.light as ColorScheme?)
}
}
}
.toolbar {
ToolbarItem(placement: .confirmationAction) {
Button("Done") {
dismiss()
}
}
}
}
}
}
#Preview {
ContentView()
}
@Vignesh19y9
Copy link

had a similar issue, and it seems like UITraitCollection.current.userInterfaceStyle returns the last value that was set, not the system value. If you set dark mode and then call it, it will only return dark mode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment