Appearance proxies / UI_APPEARANCE_SELECTOR in Swift?

SwiftUikitUiappearance

Swift Problem Overview


The Apple documentation states:

> To participate in the appearance proxy API, tag your appearance > property selectors in your header with UI_APPEARANCE_SELECTOR.

In Objective-C one can annotate properties with UI_APPEARANCE_SELECTOR like this:

@property (nonatomic, strong) UIColor *foregroundColor UI_APPEARANCE_SELECTOR;

How can I do the same in Swift?

Swift Solutions


Solution 1 - Swift

Mark your custom view property as dynamic.

For example:

class YourCustomView: UIView {
    @objc dynamic var subviewColor: UIColor? {
        get { return self.yourSubview.backgroundColor }
        set { self.yourSubview.backgroundColor = newValue }
    }
    ...
}

Then:

YourCustomView.appearance().subviewColor = UIColor.greenColor()

Solution 2 - Swift

I did not find the solution but a workaround. Instead of annotating the properties I made them as a class variable.

private struct StarFillColor { static var _color = UIColor.blackColor() }
internal class var starFillColor: UIColor {
    get { return StarFillColor._color }
    set { StarFillColor._color = newValue }
}

And in the file where I setup all my appearances:

MyClass.starFillColor = UIColor.r(181, g: 60, b: 109) 

I hope it will help somebody!

Solution 3 - Swift

In Swift, you don't need (actually, you cannot) to annotate properties with UI_APPEARANCE_SELECTOR .

Just make sure your appearance property accessor methods be of the form:

> func propertyForAxis1(axis1: IntegerType, axis2: IntegerType, axisN: IntegerType) -> PropertyType > func setProperty(property: PropertyType, forAxis1 axis1: IntegerType, axis2: IntegerType) > Source: Apple Documentation

For example:

func setStarViewColor(color: UIColor) {
    self.backgroundColor = color
}

Then you can set your appearance property like this:

MyView.appearance().setStarViewColor(someColor)

I currently using this solution in my Swift project and it works, hope it's helpful to you too.

Solution 4 - Swift

Based on previous answers, here is the extension to UIView I implemented to manage UIView appearance with view borders, I hope it can help someone :

extension UIView {
    @objc dynamic  var borderColor: UIColor? {
        get {
            if let color = self.layer.borderColor {
                return UIColor(cgColor: color)
            } else {
                return nil
            }
        }
        set(color) {
            self.layer.borderColor = color?.cgColor
        }
    }

    @objc dynamic  var borderWidth: NSNumber? {
        get { return NSNumber(value: Float(self.layer.borderWidth))}
        set(width) {
            self.layer.borderWidth = CGFloat(width?.floatValue ?? 0)
        }
    }

    @objc dynamic  var cornerRadius: NSNumber? {
        get { return NSNumber(value: Float(self.layer.cornerRadius))}
        set(radius) {
            self.layer.cornerRadius = CGFloat(radius?.floatValue ?? 0)
        }
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKlaasView Question on Stackoverflow
Solution 1 - SwiftYoichi TagayaView Answer on Stackoverflow
Solution 2 - SwiftKevin DelordView Answer on Stackoverflow
Solution 3 - SwiftguojiuboView Answer on Stackoverflow
Solution 4 - SwiftClimbatizeView Answer on Stackoverflow