在Swift的属性包装器内部,你是否可以引用拥有被包装属性的类或结构体的实例?使用
self
显然不起作用,super
也不行。我尝试将self
传递给属性包装器的init()
,但这也不起作用,因为当评估@propertywrapper
时,Configuration
上的self
还未定义。我的使用场景是在管理大量设置或配置的类中。如果更改任何属性,我只想通知感兴趣的方面某些事情已经改变。他们并不需要知道哪个值刚刚发生了变化,所以不需要为每个属性使用像KVO
或Publisher
这样的东西。属性包装器看起来很理想,但我无法弄清楚如何传递某种引用到包装器可以回调到的拥有实例。 参考: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...
}
}
didSet
属性观察器更简单。如果您需要使用Recorded
包装器注释1000个属性并且必须调整,则可以剪切和粘贴didSet { self.propertyWasSet(.textColor) }
- 如果适合您,甚至可以考虑放弃PropertyIdentifier
并改用KeyPath
。 - ctietze.m
实现,但我希望有一个更Swift的解决方案。 - kennycdidSet
属性观察器:将差分添加到您的辅助函数中,并使用propertyWasSet(.textColor,oldValue,textColor)
调用它来执行其操作。这是一种有点有状态的操作。有些人已经将差分部分称为视图模型;而Configuration
订阅自己的更改事实使其成为一种反应绑定情况。您可以将此知识提升到包装该属性的类型中,例如Binding<NSColor,Configuration>
并将self
传递给其中。 - ctietze