Search code examples
iosswiftios13ios-darkmode

Possible to reload app when dark/light mode changes?


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)?


Edit with Solution:

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.

GradientView.swift


Solution

  • 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.