Post

Replies

Boosts

Views

Activity

Reply to Dark mode toggle override - how to revert to system control?
Update: It’s better to use preferredColorScheme(), otherwise you need to style the status bar and some swiftui view’s don’t style properly with colorScheme(). So, my strategy is to cache the current device color scheme on load (by reading the .colorScheme environment variable) and basically revert the color scheme to that when the end user wants to go back to ‘auto’ mode. However, it seems that you ultimately need to pass nil to preferredColorScheme() to react to system color scheme changes (this isn’t documented), so you can kick off a background task to set this to nil after you revert to the cached original color scheme. The only edge case where this doesn’t set the correct color scheme is if the system color scheme changes after your app launched.
Sep ’20
Reply to Dark mode toggle override - how to revert to system control?
I ran into the same issue. This is more complex than it needs to be, but at present, the key is to (1) track the state of the device color scheme; (2) track the state of the end user's preferred color scheme choice (e.g. in a ObservableObject with a @Published variable; you need to track more than just isDarkMode like you did - auto/system, light, and dark); (3) independently track the end user's preferred color scheme choice in a @AppStorage variable, and (4) use colorScheme() vice preferredColorScheme(). As you can see below, I'm reacting to changes in the system color scheme using the new (in iOS 14) .onChange() functionality. If you use .preferredColorScheme() instead of .colorScheme(), the aforementioned .onChange() doesn't fire for some reason (possibly a bug). In my testing so far, when using .colorScheme(), the below .onChange() fires every time the end user changes the system level color scheme. Here's a quick example: struct ContentView: View {     #if os(iOS)     @Environment(\.horizontalSizeClass) private var horizontalSizeClass // This encapsulates the @AppStorage and @Publisher variables // that I mentioned above     @EnvironmentObject private var preferences:PreferencesStore //     @Environment(\.colorScheme) var deviceColorScheme: ColorScheme     #endif     @ViewBuilder var body: some View {         Group {             if preferences.isCompactInterface(idiom: horizontalSizeClass!) {                 TabBarContentView()] // .colorScheme() instead of .preferredColorScheme()                 .colorScheme(preferences.colorScheme.systemColorScheme())             } else {                 SideBarContentView()                 .colorScheme(preferences.colorScheme.systemColorScheme())             }             #else // MacOS code here...             #endif         }.onChange(of: deviceColorScheme) { newValue in             #if os(iOS)             // Update the current device configuration             PreferencesStore.deviceColorScheme = newValue // If the end user is in 'auto' mode, meaning let the system dictate // the color scheme...             if preferences.appColorScheme == 0 {                 if PreferencesStore.deviceColorScheme == .light {                     preferences.colorScheme = .light                 } else {                     preferences.colorScheme = .dark                 }             }             #endif         }.onAppear {             #if os(iOS) // Set the current device configuration             PreferencesStore.deviceColorScheme = deviceColorScheme             #endif         }     } } public enum InternalColorScheme {     case initial, auto, light, dark     init(code:Int) {         if code == 0 {             self = .auto         } else if code == 1 {             self = .light         } else {             self = .dark         }     }     public func systemColorScheme() -> ColorScheme {         if self == .auto || self == .initial {             return PreferencesStore.deviceColorScheme         } else if self == .light {             return .light         } else {             return .dark         }     } } class PreferencesStore: ObservableObject {          //     // START: COLOR SCHEME     //     // 0: auto     // 1: light     // 2: dark     //     // See updateStoredColorScheme() below     //     @AppStorage(wrappedValue: 2, "colorScheme")     public var appColorScheme:Int     // Update this to change how the entire view hierarchy looks     @Published public var colorScheme:InternalColorScheme = .initial     // Updated in ContentView() via an onChange() listener     public static var deviceColorScheme:ColorScheme = .light     //     // END: COLOR SCHEME     //     init() {         // Default to what is stored in UserDefaults, which causes the entire // view hierarchy the update via .colorScheme() because colorScheme // is a @Published variable         self.colorScheme = InternalColorScheme(code: appColorScheme)     } // call this when the end user wants to change the color scheme     public func updateStoredColorScheme(colorScheme:InternalColorScheme) {         if colorScheme == .auto { // update UserDefaults             appColorScheme = 0 // Change the appearance             if PreferencesStore.deviceColorScheme == .light {                 self.colorScheme = .light             } else {                 self.colorScheme = .dark             }         } else if colorScheme == .light {             appColorScheme = 1             self.colorScheme = .light         } else {             appColorScheme = 2             self.colorScheme = .dark         }     } } You can easily update you modifier code to use colorScheme() and use the above code as a basis to implement the state management I talked about. Let me know if that doesn't make sense. This implementation isn't perfect. I'm currently running into some edge cases when using .sheet().
Aug ’20
Reply to iOS 14 translate API
I’ll second that request. I would definitely be interested in access to the underlying on-device api that the new iOS 14 translate app uses. I’m currently using google translate via firebase, but would prefer to get rid of this dependency.
Jul ’20