ken*_*nyc 8 swift swift5 combine
从Swift的属性包装器中,您可以有人引用拥有被包装属性的类实例或被删除的实例吗?使用self显然不起作用,也不起作用super。
我试图传递self给属性包装器,init()但这也不起作用,因为self在评估Configuration时on 尚未定义@propertywrapper。
我的用例在用于管理大量设置或配置的类中。如果有任何属性更改,我只想通知感兴趣的人某些更改。他们实际上并不需要只知道哪个值,因此实际上不必为每个属性使用KVO或Publisher。
属性包装器看起来很理想,但是我不知道如何传递对包装器可以回调的拥有实例的某种引用。
参考文献:
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...
}
}
Run Code Online (Sandbox Code Playgroud)
小智 7
目前您无法开箱即用地执行此操作。
但是,您提到的提案将此作为最新版本中的未来方向进行讨论: https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md#referencing-the-将自我封闭在包装类型中
现在,您可以使用 aprojectedValue来分配self给。然后,您可以在设置wrappedValue.
举个例子:
import Foundation
@propertyWrapper
class 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)
Run Code Online (Sandbox Code Playgroud)
答案是否定的,当前规范是不可能的。
我想做类似的事情。我能想到的最好的方法是在末尾的函数中使用反射init(...)。至少通过这种方式,您可以注释类型,并且仅在中添加单个函数调用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
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
696 次 |
| 最近记录: |