Swift Property Wrapper是否可以引用其包装的财产的所有者? [英] Can a Swift Property Wrapper reference the owner of the property its wrapping?

查看:30
本文介绍了Swift Property Wrapper是否可以引用其包装的财产的所有者?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从Swift的属性包装器中,您可以有人引用拥有被包装的属性的类实例或被删除的实例吗?使用 self 显然不起作用, super 也不起作用.

From within a property wrapper in Swift, can you someone refer back to the instance of the class or struck that owns the property being wrapped? Using self doesn't obviously work, nor does super.

我试图将 self 传递给属性包装器的 init(),但这也不起作用,因为上的 self 评估 @propertywrapper 时,尚未定义配置.

I tried to pass in self to the property wrapper's init() but that doesn't work either because self on Configuration is not yet defined when @propertywrapper is evaluated.

我的用例在用于管理大量设置或配置的类中.如果有任何属性更改,我只想通知感兴趣的人某些事情已更改.他们真的不需要只知道哪个值,因此实际上不必为每个属性使用 KVO Publisher 之类的东西.

My use case is in a class for managing a large number of settings or configurations. If any property is changed, I just want to notify interested parties that something changed. They don't really need to know which value just, so use something like KVO or a Publisher for each property isn't really necessary.

属性包装器看起来很理想,但是我不知道如何传递对包装器可以回调的拥有实例的某种引用.

A property wrapper looks ideal, but I can't figure out how to pass in some sort of reference to the owning instance that the wrapper can call back to.

参考:

SE-0258

enum PropertyIdentifier {
  case backgroundColor
  case textColor
}

@propertyWrapper
struct Recorded<T> {
  let identifier:PropertyIdentifier
  var _value: T

  init(_ identifier:PropertyIdentifier, defaultValue: T) {
    self.identifier = identifier
    self._value = defaultValue
  }

  var value: T {
    get {  _value }
    set {
      _value = newValue

      // How to callback to Configuration.propertyWasSet()?
      //
      // [self/super/...].propertyWasSet(identifier)
    }
  }
}

struct Configuration {

  @Recorded(.backgroundColor, defaultValue:NSColor.white)
  var backgroundColor:NSColor

  @Recorded(.textColor, defaultValue:NSColor.black)
  var textColor:NSColor

  func propertyWasSet(_ identifier:PropertyIdentifier) {
    // Do something...
  }
}

推荐答案

答案是否定的,当前规范是不可能的.

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

我想做类似的事情.我能想到的最好的方法是在 init(...)末尾的函数中使用反射.至少通过这种方式,您可以注释类型,并且仅在 init()中添加单个函数调用.

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 }
}

@propertyDelegate
class 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
            }
        }
    }
}

这篇关于Swift Property Wrapper是否可以引用其包装的财产的所有者?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆