0

I have updated views in my app to support dark mode by adding

        if #available(iOS 12.0, *) {
           if self.traitCollection.userInterfaceStyle == .dark {
               //Adapt to dark Bg
           } else {
                //Adapt to light Bg
            }
        }

Then, to allow for the case where the user backgrounds the app and returns to it after switching mode, I attach an observer in my viewDidLoad

        if #available(iOS 12.0, *) {
            NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
        } else {
            // Fallback on earlier versions
        }

which triggers the function

    @available(iOS 12.0, *)
    @objc func willEnterForeground() {
        if self.traitCollection.userInterfaceStyle == .dark {
            print("App moving to foreground - dark")
            //Adapt to dark Bg
        } else {
            print("App moving to foreground - light")
            //Adapt to light Bg
        }
    }

However, self.traitCollection.userInterfaceStyle still gives the old value so a full reload of the view is required to produce the desired update to the interface. Using UIApplication.didBecomeActiveNotification instead makes no difference.

eggdeng
  • 148
  • 9

1 Answers1

4

You don't need all those messy if statements! Just add your colours to your Asset Catalogue and the right one will automatically be selected. This is similar to how you can add x1, x2 and x3 images, and the right one will be selected.

Go to the Asset Catalogue and at the bottom left, click on the plus button, select "New Color Set":

enter image description here

Give the colour a name, and in the property inspector, set "Appearance" to "Any, Dark":

enter image description here

Choose a colour for each appearance:

enter image description here

Finally, use the UIColor(named:) initialiser to initialise the colours and they will automatically change when the device's dark mode settings change:

someView.backgroundColor = UIColor(named: "myColor")

EDIT:

If the colours are only known at runtime, you can use the init(dynamicProvider:) initialiser (iOS 13 only though):

someView.backgroundColor = UIColor {
    traits in
    if traits.userInterfaceStyle == .dark {
        // return color for dark mode
    } else {
        // return color for light mode
    }
}
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • That would certainly make life a lot easier. Unfortunately, the colours I am dealing with are embedded in a long html string as . So I don't see how I could use it here. – eggdeng Mar 01 '20 at 15:09
  • @eggdeng I found [this initialiser](https://developer.apple.com/documentation/uikit/uicolor/3238041-init). I guess you could pass a closure to it, and put your if statement in the closure? – Sweeper Mar 01 '20 at 15:12
  • Thanks for the suggestions. I tried both and both seem to switch the color but instead of switching between black and white, they switch between cherry red and cherry red! I think the remaining issue is with the conversion from HTML so I'm going to accept the answer. – eggdeng Mar 01 '20 at 16:14