/AssociatedObject

๐Ÿ”— Swift Macro for allowing variable declarations even in class extensions

Primary LanguageSwiftMIT LicenseMIT

AssociatedObject

Swift Macro for allowing variable declarations even in class extensions. It is implemented by wrapping objc_getAssociatedObject/objc_setAssociatedObject.

Github issues Github forks Github stars Github top language

Usage

For example, you can add a new stored property to UIViewController by declaring the following

import AssociatedObject

extension UIViewController {
    @AssociatedObject(.retain(nonatomic))
    var text = "text"

    /* OR */

    @AssociatedObject(.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    var text = "text"
}

Declared properties can be used as follows

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        print(text) // => "text"

        text = "hello"
        print(text) // => "hello"
    }

}

willSet/didSet

Properties defined using @AssociatedObject can implement willSet and didSet. In swift, it is not possible to implement willSet and didSet at the same time as setter, so they are expanded as follows.

@AssociatedObject(.copy(nonatomic))
public var hello: String = "ใ“ใ‚“ใซใกใฏ" {
    didSet {
        print("didSet")
    }
    willSet {
        print("willSet: \(newValue)")
    }
}

// โ†“โ†“โ†“ expand to ... โ†“โ†“โ†“
public var hello: String = "ใ“ใ‚“ใซใกใฏ" {
    get {
        objc_getAssociatedObject(
            self,
            &Self.__associated_helloKey
        ) as? String
        ?? "ใ“ใ‚“ใซใกใฏ"
    }

    set {
        let willSet: (String) -> Void = { [self] newValue in
            print("willSet: \(newValue)")
        }
        willSet(newValue)

        let oldValue = hello

        objc_setAssociatedObject(
            self,
            &Self.__associated_helloKey,
            newValue,
            .copy(nonatomic)
        )

        let didSet: (String) -> Void = { [self] oldValue in
            print("didSet")
        }
        didSet(oldValue)
    }
}

License

AssociatedObject is released under the MIT License. See LICENSE