issue cgColor switching in iOS 13 dark mode

4.1k views Asked by At

I'm facing trouble switching colours when change mode in iOS 13.

The problem is when you see the app in recent apps. UIColors will change but cgColor will not change.

It will change effectively when you open the app but just in recent it will not change.

I'm using "traitCollectionDidChange" method as mentioned in following apple's document. https://developer.apple.com/documentation/xcode/supporting_dark_mode_in_your_interface


Please have a look at Video to understand more clearly https://www.youtube.com/watch?v=C-pcVuPMQ9U&feature=youtu.be


class ViewController: UIViewController {

    @IBOutlet weak var viewColor: UIView!
    let layerColor = CALayer()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        setLayer()
        setColors()
    }

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)

        if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
            setColors()
        }
    }

    func setColors() {
        layerColor.backgroundColor = UIColor(named: "layerColor")?.cgColor
    }

    func setLayer() {
        layerColor.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
        viewColor.layer.addSublayer(layerColor)
    }
}
5

There are 5 answers

1
Jawad Ali On

For cgColor you need to use

layerColor.backgroundColor = UIColor(named: "layerColor")?.resolvedColor(with: self.traitCollection).cgColor
2
Khushal iOS On

your all app with one line solution here,

just you put this line in your appDelegate file

if #available(iOS 13.0, *) {
    window?.overrideUserInterfaceStyle = .light
}

OR . you can add in info.plist like this

<key>UIUserInterfaceStyle</key>
<string>Light</string>
0
Mig70 On

I had the same problem. I solved it by removing the sublayer, recreating it and adding this new one with the desired color. It works both on iOS13 and iOS14.

1
Daniel Smith On

When you change mode traitCollectionDidChange is called


class YourView: UIView {

  override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)

    self.layer.shadowColor = yourUIColor.cgColor
  }

}
0
Wei On

Lower-level classes, like CA Layer and CG Color, don't understand dynamic colors. It's a UIKit concept.

ref: https://developer.apple.com/videos/play/wwdc2019/214/?time=1415

For UIView, I spent lots time to figure out; therefore, I resolve the issue with

    
    override open func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        guard traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) else { return }
        customizeUpdateLayers()
    }
    func customizeUpdateLayers() {
        // do sth
    }

For NSView, move that code to your view’s updateLayer() method instead...

ref: https://developer.apple.com/documentation/uikit/appearance_customization/supporting_dark_mode_in_your_interface#2993898

ref: func updateLayer