4

众所周知,当然,didSet 不会再次从 didSet 内部在同一个对象上运行。(例如。)

然而。似乎:限制不仅适用于该对象,而且可能适用于同一类的任何对象

这是 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

不工作!

  1. 这是一个 Swift 错误吗?

  2. 如果没有,实际的限制是什么?它不会运行从 didSet 开始的任何 didSet(无论如何)?同一个班级?;同一个超级班?或者?

  3. 这在doco中到底是在哪里解释的?

哇。需要知道......具体的实际限制是什么?

4

1 回答 1

1

这是错误SR-419

从对错误的评论中:

啊。我们确实需要检查属性访问的基础是静态的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
       }()
    }
}

根据闭包之前的代码,您可能必须将其包装在括号中或在前面的语句之后插入分号。

于 2017-02-12T14:10:47.360 回答