Swift Macro for allowing variable declarations even in class extensions.
It is implemented by wrapping objc_getAssociatedObject
/objc_setAssociatedObject
.
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"
}
}
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)
}
}
AssociatedObject is released under the MIT License. See LICENSE