内部 didSet 保护奇怪地扩展到整个 class?
Inner didSet protection bizarrely extends to the whole class?
众所周知,didSet 当然不会 运行 再次从 didSet 内部对同一个对象进行处理。 (.)
不过。似乎:限制不仅适用于该对象,而且可能 同一对象的任何对象 class.
这里是 Playground 的复制粘贴测试用例。
class C {
var Test: Bool = false {
didSet {
print("test.")
for c in r {
c.Test = true
}
}
}
var r:[C] = []
}
var a:C = C()
var b:C = C()
var c:C = C()
a.r = [b, c]
a.Test = false
无效!
class C {
var Test2: Bool = false {
didSet {
print("test2.")
global.Test2 = true
}
}
}
var global:C = C()
var a:C = C()
a.Test2 = false
无效!
这是 Swift 错误吗?
如果没有,实际限制是什么?它不会 运行 任何从 didSet 开始的 didSet(无论如何)?相同的 class?;同超class?;或者?
doco 中的具体解释是什么?
WTF。需要知道...具体的实际限制是什么?
这是错误 SR-419。
来自对错误的评论:
Ugh. We really need to check that the base of the property access is statically self
.
从我的实验来看,似乎 didSet
观察者只有在您对任何对象设置相同的 属性 时才会被调用。如果您设置任何其他 属性(即使在同一个对象上),也会正确调用观察者。
class A {
var name: String
var related: A?
var property1: Int = 0 {
didSet {
print("\(name), setting property 1: \(property1)")
self.property2 = 100 * property1
related?.property1 = 10 * property1
related?.property2 = 100 * property1
}
}
var property2: Int = 0 {
didSet {
print("\(name), setting property 2: \(property2)")
}
}
init(name: String) {
self.name = name
}
}
let a = A(name: "Base")
a.related = A(name: "Related")
a.property1 = 2
输出:
Base, setting property 1: 2
Base, setting property 2: 200
Related, setting property 2: 200
当预期输出应该是:
Base, setting property 1: 2
Base, setting property 2: 200
Related, setting property 1: 20
Related, setting property 2: 2000
Related, setting property 2: 200
看来您还需要从观察者那里直接属性 分配。一旦你进入另一个函数(或观察者),观察者又开始工作了:
var property1: Int = 0 {
didSet {
print("\(name), setting property 1: \(property1)")
onSet()
}
}
...
func onSet() {
self.property2 = 100 * property1
related?.property1 = 10 * property1
related?.property2 = 100 * property1
}
这是最好的解决方法。
另一种解决方法(感谢 @Hamish)是将嵌套赋值包装到立即执行的闭包中:
var property1: Int = 0 {
didSet {
{
self.property2 = 100 * property1
related?.property1 = 10 * property1
related?.property2 = 100 * property1
}()
}
}
根据闭包前的代码,您可能必须将其括在括号中或在前面的语句后插入分号。
众所周知,didSet 当然不会 运行 再次从 didSet 内部对同一个对象进行处理。 (
不过。似乎:限制不仅适用于该对象,而且可能 同一对象的任何对象 class.
这里是 Playground 的复制粘贴测试用例。
class C {
var Test: Bool = false {
didSet {
print("test.")
for c in r {
c.Test = true
}
}
}
var r:[C] = []
}
var a:C = C()
var b:C = C()
var c:C = C()
a.r = [b, c]
a.Test = false
无效!
class C {
var Test2: Bool = false {
didSet {
print("test2.")
global.Test2 = true
}
}
}
var global:C = C()
var a:C = C()
a.Test2 = false
无效!
这是 Swift 错误吗?
如果没有,实际限制是什么?它不会 运行 任何从 didSet 开始的 didSet(无论如何)?相同的 class?;同超class?;或者?
doco 中的具体解释是什么?
WTF。需要知道...具体的实际限制是什么?
这是错误 SR-419。
来自对错误的评论:
Ugh. We really need to check that the base of the property access is statically
self
.
从我的实验来看,似乎 didSet
观察者只有在您对任何对象设置相同的 属性 时才会被调用。如果您设置任何其他 属性(即使在同一个对象上),也会正确调用观察者。
class A {
var name: String
var related: A?
var property1: Int = 0 {
didSet {
print("\(name), setting property 1: \(property1)")
self.property2 = 100 * property1
related?.property1 = 10 * property1
related?.property2 = 100 * property1
}
}
var property2: Int = 0 {
didSet {
print("\(name), setting property 2: \(property2)")
}
}
init(name: String) {
self.name = name
}
}
let a = A(name: "Base")
a.related = A(name: "Related")
a.property1 = 2
输出:
Base, setting property 1: 2
Base, setting property 2: 200
Related, setting property 2: 200
当预期输出应该是:
Base, setting property 1: 2
Base, setting property 2: 200
Related, setting property 1: 20
Related, setting property 2: 2000
Related, setting property 2: 200
看来您还需要从观察者那里直接属性 分配。一旦你进入另一个函数(或观察者),观察者又开始工作了:
var property1: Int = 0 {
didSet {
print("\(name), setting property 1: \(property1)")
onSet()
}
}
...
func onSet() {
self.property2 = 100 * property1
related?.property1 = 10 * property1
related?.property2 = 100 * property1
}
这是最好的解决方法。
另一种解决方法(感谢 @Hamish)是将嵌套赋值包装到立即执行的闭包中:
var property1: Int = 0 {
didSet {
{
self.property2 = 100 * property1
related?.property1 = 10 * property1
related?.property2 = 100 * property1
}()
}
}
根据闭包前的代码,您可能必须将其括在括号中或在前面的语句后插入分号。