Set button border according to light/dark mode

Xcode 12.5/iOS 13+/Swift 5

I've got multiple UIButtons and I change their border color in their "Identity Inspector" with borderColor set to the custom ColorSet "ButtonBorderColor".

The button's text and background change properly when I switch to dark mode but the border doesn't. According to Stackexchange you have to override traitCollectionDidChange like this:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    if (traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection)) {
        layer.borderColor = UIColor(named: "ButtonBorderColor")!.cgColor
    }
}

But where do you put this, so it affects every button in my app? I tried to add it to an extension UIButton {}, which told me to add open to the function but the color doesn't change when I switch mode.

It seems correct to put it in UIButton extension, but I am not sure that traitCollectionDidChange is a solution because you are not in your app when trait changement occurred and so your code is not executed.

Using sort of dynamic color seems to be a better option. Define a light and dark color in your Color Set if you use Asset Catalog or use UIColor init(dynamicProvider:) initializer.

Something like this :

    static var myBorderColor: UIColor {
        if #available(iOS 13.0, *) {
            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)
            }
        } else {
            //  iOS 12 and earlier, no dark mode 
            return UIColor(red: 0.3, green: 0.4, blue: 0.5, alpha: 1)
        }
    }
}
Set button border according to light/dark mode
 
 
Q