I have a navigation app. During a navigation session, I prevent the screen from sleeping. When users are driving/navigating around sunrise or sunset, appearance should change between light and dark mode.
In order to do this, I created a subclass of UIWindow:
class WindowWithDarkModeMonitor: UIWindow {
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
print("traitCollectionDidChange")
}
}
traitCollectionDidChange
is supposed to be called whenever traits (like portrait/landscape and dark/light mode change). (Apple Documentation (b.t.w. I know this method will be deprecated, but my app needs to support iOS16 for the moment, so I still need it).
Now, the problem is, traitCollectionDidChange
is not called on a scheduled appearance change. It IS called when I switch between dark and light mode through the control center. It's also called when I rotate my device.
I browsed a LOT, and have tried a LOT, but can't find a solution. This SO question comes close, but the top (and only) answer doesn't work for my case either.
After some testing, I actually found out that no app I know of changes from dark to light or vice versa when it's active in the foreground at the time of the scheduled change. You can try this yourself:
- Go to iOS Settings > Display & Brightness
- Set appearance to AUTOMATIC and for Options choose 'Custom Schedule' and choose the times so that a change is 1 or 2 minutes away.
- Now open Apple Mail, or Safari, or any other app that supports dark mode
- Make sure your display doesn't go to sleep, and wait until the minute passes where the dark/light switch should take place.
- Nothing happens!!!
- The dark/light switch is only applied after your iPhone is auto-locked or locked manually, and unlocked again.
I have a very strong feeling this is either an iOS bug (or a 'feature'?). In any case, it would be unfortunate for an app like mine, if I couldn't use the system's automatic dark/light switch at sunset/sunrise. I would have to build my own solution to determine if it's day or night (based on location and time zone). Not impossible, but I'd rather not re-invent the wheel, and keep my app as close to system behavior as possible.
So, is there any way to make the system call traitCollectionDidChange
upon a scheduled appearance change (dark/light mode change)? Or, any other way to get notified about this?