My app makes extensive use of CAGradientLayers which apparently do not automatically update their colors when dark/light mode is switched. They will update their colors when the app is closed and reopened though.
Im aware i can use the following code to detect the change and reload each view individually
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
//
}
However I am looking for a fix that does not require me to update each view individually. Is there a way to detect a light/dark mode change (possibly within the app delegate) and force the entire app to reload itself (as if it had been force closed and reopened)?
The app cannot be reloaded in the way I'd originally imagined however there is a fairly simple solution that is much cleaner.
As stated in the accepted answer, a subclass of UIView
can be created that contains a CAGradientLayer
as a sublayer. You can then override traitCollectionDidChange
to reload the view automatically when the system style changes. The key is to remember that UIColors
automatically update when system style changes but CGColors
do not automatically update. So you'll need to store the original UIColor
for the gradient and convert the UIColor
back to a CGColor
every time the system style is updated.
Linked below is a Github Gist with a very basic implementation of a "Gradient View" that will automatically respond to light & dark mode changes. It can be added as a subview to other views or modified as needed.
There is no way to "reload your app" in this way. The issue arises because CAGradientLayer
uses CGColor
, which doesn't dynamically adapt to the system style.
I resolved the issue by wrapping a UIView
around the gradient layer that implements traitCollectionDidChange
to update the gradient's colors accordingly. Maybe you can do the same and use this as subview instead of a sublayer.