你如何从@propertywrapper 中公开闭包?

How do you expose a closure from within a @propertywrapper?

我正在尝试编写一个 属性 包装器来将两个变量绑定在一起。我遇到的问题是,当我调用 projectedValue 属性 我的闭包 returns 为零时。一旦观察项的值发生更改,我希望能够为闭包分配一个值。

这是我的 属性 包装纸 class。

@propertyWrapper
class State<Instance> {

    typealias projectedClosure = (Instance) ->Void


    init(wrappedValue: Instance) {
        self.instance = wrappedValue
    }

     var projectedValue : Binding<Instance>  {
        Binding<Instance>(value: instance)
    }

    private var instance : Instance {
        didSet{
            projectedValue.value = instance
        }
    }

    var wrappedValue: Instance {
        get{
            return instance
        }
        set{
            instance = newValue
        }
    }
}

属性Wrapper 投射这个 class

class Binding<Element> {

    var handler : ((Element)->Void)?

    var value :Element {
        didSet{
            guard let handlerClosure = handler else {
                print("Handler is null")
                return
            }
            handlerClosure(value)
        }
    }

    init(value:Element) {
        self.value = value
    }
}

最后,在将它移植到我的实际项目中之前,我在操场上实现了它。这就是我执行这些方法的方式。

class TestPropertyWrapperObserver {

    @State var name : String

    init(name:String) {
        self.name = name
    }
}

var test = TestPropertyWrapperObserver(name: "Thomas")

var ryan = "ryan"

test.$name.handler = { item in
    ryan = item
    print(item)
}

test.name = "bradly"
test.name = "fake"

print(ryan)

我的打印日志是:

Handler is null
Handler is null
ryan

你的错误是你 projectedValue 计算了 属性,所以每次你这样做时:

projectedValue.value = instance

创建了一个new Binding实例。

相反,您应该将 projectedValue 存储为 属性,并在 init 中初始化它,一次:

init(wrappedValue: Instance) {
    self.instance = wrappedValue
    projectedValue = Binding<Instance>(value: instance)
}

let projectedValue : Binding<Instance>