Some of the UI setups not working automatically with the Dark/Light mode change as the UIColor
. For example shadow
in layer. As I need to remove and drop shadow in dark and light mode, I need somewhere to put updateShadowIfNeeded()
function. I know how to detect what is the mode currently:
func dropShadowIfNeeded() {
switch traitCollection.userInterfaceStyle {
case .dark: removeShadow()
case .light: dropShadowIfNotDroppedYet()
default: assertionFailure("Unknown userInterfaceStyle")
}
}
Now I put the function inside the layoutSubviews
, since it gets called every time appearance change:
override func layoutSubviews() {
super.layoutSubviews()
dropShadowIfNeeded()
}
But this function is getting called A LOT. What is the proper function to trigger only if userInterfaceStyle
changed?
Dark mode can be detected by using the userInterfaceStyle property on the current trait collection. When it's set to dark you know that the current appearance is set to dark.
The Box Mobile team is excited to announce the Box iOS app now offers Dark Mode support for an optimal viewing experience in low-light environments. Dark Mode will be supported on devices with iOS 13 and higher. To enable Dark Mode, go to your device system settings (Settings-->Display & Brightness-->Dark Mode button).
We simply have to add a @Enviroment variable and use . colorScheme property to scan the settings on our device and see if dark mode is enabled. Let's take a look at the example below. struct ContentView: View { @Environment(\.
With a simple environment variable on the \.colorScheme
key:
struct ContentView: View {
@Environment(\.colorScheme) var colorScheme
var body: some View {
Text(colorScheme == .dark ? "Its Dark" : "Its. not dark! (Light)")
}
}
As it described in WWDC 2019 - Session 214 around 23:30.
As I expected, this function is getting called a lot including when colors changing. Along side with many other functions for ViewController
and presentationController
. But there is some especial function designed for that has a similar signature in all View
representers.
Take a look at this image from that session:
Gray: Calling but not good for my issue, Green: Designed for this
So I should call it and check it inside this function:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
dropShadowIfNeeded()
}
}
This will guarantee to be called just once per change.
if you are only looking for the initial state of the style, check out this answer here
I think this should get called significantly less often, plus the guard makes sure you only react to user interface style changes:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
guard previousTraitCollection?.userInterfaceStyle != traitCollection.userInterfaceStyle else {
return
}
dropShadowIfNeeded()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With