众所周知,didSet不会再从didSet内部运行在同一个对象上。 (example。)
然而。似乎:限制不仅适用于该对象,也适用于同一类的任何对象 。
以下是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(无论如何)?同一个班级?同一个超级班?或
doco究竟在哪里解释?
WTF。人们需要知道......具体的实际限制是什么?
答案 0 :(得分:1)
这是错误SR-419。
来自对bug的评论:
唉。我们确实需要检查属性访问的基础是静态
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
输出:
基地,设置属性1:2
基地,设置属性2:200
相关,设置属性2:200
当预期输出应为:
基地,设置属性1:2
基地,设置属性2:200
相关,设置属性1:20
相关,设置属性2:2000
相关,设置属性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
}()
}
}
根据闭包前的代码,您可能必须将其包装到括号中或在前面的语句后插入分号。