lundi 31 mai 2021

Using getter/setter for property makes it not appear in reflection (mirror)

I've been trying to implement a theme logic for my custom components. I'll use ZFButton as example.

When the app starts I instantiate ZFbutton and set whatever characteristics I want this one theme to have:

let theme = ZFButton()
theme.backgroundColor = .red //UIButton property
theme.cornerRadius = 8 //ZFButton property
theme.borderColor = .green //ZFButton property
theme.borderWidth = 1 //ZFButton property

Then add it to the theme array:

ZFButton.themes.append(theme)

which resides in the ZFButton as follows:

public static var themes = [ZFButton]()

In my ZFButton I have the following property, which allows me to choose from the IB Attributes Inspector which theme I want to use for that particular ZFButton

@IBInspectable public var theme: Int = 0 { didSet { self.setupTheme() } }

And finally, once the theme property is set, setupTheme() is called, in which I attempt to copy the value set from all properties of a given theme to this particular instance of ZFButton. For that I use reflection:

private func setupTheme() {
    
    if ZFButton.themes.count > self.theme {
        
        let theme = ZFButton.themes[self.theme]
        let mirror = Mirror(reflecting: theme)

        for child in mirror.children {
            
            if let label = child.label,
               label != "theme", //check to prevent recursive calls
               self.responds(to: Selector(label)) {
                   
                self.setValue(child.value, forKey: label)
                
                print("Property name:", child.label)
                print("Property value:", child.value)
            }
        }
    }
}

Now I have two problems:

1 - Properties that have setter/getter do not show up in the reflection, example:

@IBInspectable public var borderColor: UIColor {
    
    set { layer.borderColor = newValue.cgColor }
    get { return UIColor(cgColor: layer.borderColor!) }
}

Whereas properties that use didSet do, such as:

@IBInspectable public var iconText: String = "" { didSet { self.setupIcon() } }

However, I do need a getter here to return the borderColor in layer.

2 - When using Mirror to reflect all ZFButton properties, besides the issue described in (1), I don't get UIButton properties either, is there a way to get ZFButton's superclass (UIButton) as well?





Aucun commentaire:

Enregistrer un commentaire