Can a Swift Property Wrapper reference the owner of the property its wrapping? Can a Swift Property Wrapper reference the owner of the property its wrapping? swift swift

Can a Swift Property Wrapper reference the owner of the property its wrapping?


The answer is no, it's not possible with the current specification.

I wanted to do something similar. The best I could come up with was to use reflection in a function at the end of init(...). At least this way you can annotate your types and only add a single function call in init().

fileprivate protocol BindableObjectPropertySettable {    var didSet: () -> Void { get set }}@propertyDelegateclass BindableObjectProperty<T>: BindableObjectPropertySettable {    var value: T {        didSet {            self.didSet()        }    }    var didSet: () -> Void = { }    init(initialValue: T) {        self.value = initialValue    }}extension BindableObject {    // Call this at the end of init() after calling super    func bindProperties(_ didSet: @escaping () -> Void) {        let mirror = Mirror(reflecting: self)        for child in mirror.children {            if var child = child.value as? BindableObjectPropertySettable {                child.didSet = didSet            }        }    }}


You cannot do this out of the box currently.

However, the proposal you refer to discusses this as a future direction in the latest version:https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md#referencing-the-enclosing-self-in-a-wrapper-type

For now, you would be able to use a projectedValue to assign self to.You could then use that to trigger some action after setting the wrappedValue.

As an example:

import Foundation@propertyWrapperclass Wrapper {    let name : String    var value = 0    weak var owner : Owner?    init(_ name: String) {        self.name = name    }    var wrappedValue : Int {        get { value }        set {            value = 0            owner?.wrapperDidSet(name: name)        }    }    var projectedValue : Wrapper {        self    }}class Owner {    @Wrapper("a") var a : Int    @Wrapper("b") var b : Int    init() {        $a.owner = self        $b.owner = self    }    func wrapperDidSet(name: String) {        print("WrapperDidSet(\(name))")    }}var owner = Owner()owner.a = 4 // Prints: WrapperDidSet(a)


My experiments based on : https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md#referencing-the-enclosing-self-in-a-wrapper-type

protocol Observer: AnyObject {    func observableValueDidChange<T>(newValue: T)}@propertyWrapperpublic struct Observable<T: Equatable> {    public var stored: T    weak var observer: Observer?    init(wrappedValue: T, observer: Observer?) {        self.stored = wrappedValue    }    public var wrappedValue: T {        get { return stored }        set {            if newValue != stored {                observer?.observableValueDidChange(newValue: newValue)            }            stored = newValue        }    }}class testClass: Observer {    @Observable(observer: nil) var some: Int = 2    func observableValueDidChange<T>(newValue: T) {        print("lol")    }    init(){        _some.observer = self    }}let a = testClass()a.some = 4a.some = 6