Skip to content

A property wrapper intended to reduce boilerplate of proxy properties

License

Notifications You must be signed in to change notification settings

theoriginalbit/ProxyPropertyWrapper

Repository files navigation

ProxyPropertyWrapper

A property wrapper intended to reduce boilerplate of proxy properties.

Motivation

Take the following example:

class HeaderView: UIView {
    private let titleLabel = UILabel()
}

In order to allow owning objects to set the text value of titleLabel it's common place for developers to go one of two implementations…

The first implementation

Removing the private access modifier:

class HeaderView: UIView {
    let titleLabel = UILabel()
}

This approach is bad as it exposes implementation details—which should they change then bubbles around the rest of the code—and also exposes the label for other properties being set which could lead to bugs, unexpected behaviours, or confusion around appearance.

The second implementation

An accessor/proxy property.

class HeaderView: UIView {
    private let titleLabel = UILabel()
    
    var title: String? {
        get { titleLabel.text }
        set { titleLabel.text = newValue }
    }
}

In my experience those who know/understand the drawbacks of the first implementation will pick this approach instead.

This implementation doesn't have the same concern with exposing implementation details and also closes off the other properties for mutation, removing a large potential for bugs. The drawback this approach introduces is a large amount of boilerplate, with potential for typos especially copy/pasta typos. For example:

class HeaderView: UIView {
    private let titleLabel = UILabel()
    private let subtitleLabel = UILabel()
    
    var title: String? {
        get { titleLabel.text }
        set { titleLabel.text = newValue }
    }
    
    var subtitle: String? {
        get { subtitleLabel.text }
        set { titleLabel.text = newValue } // 🛑 references titleLabel, should reference subtitleLabel
    }
}

This library to the rescue

This is where this library comes in, using an accessor/proxy property like in the second implementation but without all the boilerplate.

class HeaderView: UIView {
    private let titleLabel = UILabel()
    private let subtitleLabel = UILabel()
    
    @Proxy(\.titleLabel.text) var title
    @Proxy(\.subtitleLabel.text) var subtitle
}

As an added bonus we can also choose to omit the type information (: String?) from the property too, as the compiler can infer it from the key path, further reducing the boilerplate we must type.

About

A property wrapper intended to reduce boilerplate of proxy properties

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages