1

We can use dynamic providers to extent UIColor classes and have colors that change immediately to dark and light modes, like this

extension UIColor {
  static var myControlBackground: UIColor {
      return UIColor { (traits) -> UIColor in
        // Return one of two colors depending on light or dark mode
        return traits.userInterfaceStyle == .dark ?
          UIColor(red: 0.5, green: 0.4, blue: 0.3, alpha: 1) :
          UIColor(red: 0.3, green: 0.4, blue: 0.5, alpha: 1)
      }
  }
}

But what about UIImages?

I know that you can use this method

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
  if traitCollection.hasDifferentColorAppearance(comparedTo:
                                                 previousTraitCollection) {
    // Color change detected.
    // Adjust the interface accordingly.
  }
}

the problem is that this method doe not detect changes if the app is in background when the change occurs. And the color dynamic method does.

Any ideas

Duck
  • 34,902
  • 47
  • 248
  • 470
  • `traitCollectionDidChange` does not detect changes if the app is in background when the appearance changes. – Duck Apr 03 '20 at 18:25
  • I want to understand if I can do that programmatically, or in other words, without using Image Sets inside Assets Catalog. Create a way images change to their dark/light equivalents automatically when appearance changes. – Duck Apr 03 '20 at 18:34

1 Answers1

3

You are looking for the UIImageAsset class:

https://developer.apple.com/documentation/uikit/uiimageasset

Basically, you make an image asset along with versions of the UIImage for different trait collections, and call register on the image asset with the image along with its corresponding trait collection.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Excellent. I was looking for the same, BUT I would like to register images related to my own themes (not only dark or light, but also a halloween theme, for example). I do this with colors and dynamicProvider, and works great, but I'm not sure how to do that with images... Do you know @matt if that is possible? – ernewston Nov 04 '21 at 20:53
  • @ernewston How do you do it with colors and dynamic provider? You can't make up a custom trait (as far as I'm aware). – matt Nov 04 '21 at 23:32
  • `var background = UIColor { _ in switch theme { case .light: return color1 case .dark: return color2 case .halloween: return color3 } }`. I don't why apple limited appearances to only two, would be great to have N custom traits to handle themes... – ernewston Nov 05 '21 at 12:48
  • @ernewston Ah, I see. Well, that's not a color "dynamic provider". You didn't make a live dynamic color, like Apple's. Your interface colors don't magically change when you change the theme, the way Apple's do; you just made a method that returns a color at the time that you call it. Nothing special there. So you could do exactly the same with for your image. – matt Nov 05 '21 at 13:24
  • Sorry that I wasn't clear enough. The example above is the same as writing `var background = UIColor(dynamicProvider: { _ in switch theme { case .light: return color1 case .dark: return color2 case .halloween: return color3 } })`. It does magically change colors when changing darkmode/lightmode. – ernewston Nov 05 '21 at 14:24
  • 1
    @ernewston But not when changing the theme to `.halloween`. – matt Nov 05 '21 at 14:26
  • Yep, that's true. :( – ernewston Nov 05 '21 at 14:30