0

I am trying to use appearance to set general default layouts/designs across the app. For UISwitch, to set the off color not only at the border, one has to do a tweak (see Change color of UISwitch in "off" state):

uiswitch.backgroundColor = .red
uiswitch.layer.cornerRadius = 16

Whenever I do:

let toggle = UISwitch()
toggle.tintColor = offColor // see "global vars and methods below"
toggle.onTintColor = onColor
toggle.backgroundColor = offColor
toggle.layer.cornerRadius = 16
view.addSubview(toggle)
constraintToCenter(toggle: toggle)

It works and I get:

UISwitch with off color

But if I use the appearance like this:

let toggle = UISwitch()
view.addSubview(toggle)
constraintToCenter(toggle: toggle)
UISwitch.newSetUpDefaultAppearance(onColor: onColor, offColor: offColor)

public extension UISwitch {
    class func newSetUpDefaultAppearance(onColor: UIColor, offColor: UIColor) {
        let defaultAppereance = appearance(whenContainedInInstancesOf: [])
        defaultAppereance.onTintColor = onColor
        defaultAppereance.backgroundColor = offColor
        defaultAppereance.tintColor = offColor
        defaultAppereance.layer.cornerRadius = 16.0
        print (defaultAppereance.layer.cornerRadius) // prints 0.0
    }
}

I get:

enter image description here

Global vars and methods:

let onColor = UIColor.black
let offColor = UIColor.gray

func constraintToCenter(view: UIView) {
    toggle.translatesAutoresizingMaskIntoConstraints = false        
    NSLayoutConstraint.activate([toggle.centerXAnchor.constraint(equalTo: view.centerXAnchor), toggle.centerYAnchor.constraint(equalTo: view.centerYAnchor)])
}

Does someone see what I am doing wrong?

Matteo Pacini
  • 21,796
  • 7
  • 67
  • 74
regina_fallangi
  • 2,080
  • 2
  • 18
  • 38

1 Answers1

0

According to Appearance Proxies & Layers, it looks like it is not possible because CALayer does not conform to UIAppearance and does not have an appearance method.

The only way to do it is the answer by Sandy Chapman in that answer. Here is how it looks in Swift and it works:

public class Switch: UISwitch {
    // dynamic is needed for UIAppearance support
    @objc dynamic var cornerRadius: CGFloat = 0.0 {
        didSet {
            self.layer.cornerRadius = cornerRadius
        }
    }

    public class func globalDefaultAppearance() {
        let defaultAppereance = appearance(whenContainedInInstancesOf: [])
        defaultAppereance.onTintColor = .red
        defaultAppereance.backgroundColor = .yellow
        defaultAppereance.tintColor = .red
        defaultAppereance.cornerRadius = 16.0
    }
}

Using

let toggle = Switch()
UISwitch.globalSetUpDefaultAppearance()

works perfectly.

regina_fallangi
  • 2,080
  • 2
  • 18
  • 38