在设置x的属性时,将setSet / didSet调用容器的存储属性x

时间:2016-06-02 01:20:18

标签: swift swift-protocols

我观察到那些我不太了解的行为。在操场上执行此代码时:

protocol Testp {
    var notes: String { get set }
}

class Testc: Testp {
    var notes: String = "x"
}

class TestContainer {
    var test: Testp = Testc() {
        willSet {
            print("willSet")
        }
        didSet {
            print("didSet")
        }
    }
}

var testContainer = TestContainer()
print(testContainer.test.notes) // prints "x"

// this triggers a willSet+didSet call on TestContainer's
// stored property, even though "test" is not changed in testContainer
testContainer.test.notes = "y"

print(testContainer.test.notes) // prints "y"

如上所述,即使未设置属性本身,也会调用willSetdidSet块。

另一方面,如果我将协议更改为类型类,如下所示

protocol Testp: class {
    var notes: String { get set }
}

然后结果就像我预期的那样(即没有调用willSet/didSet)。

这种行为的原因是什么?

我在XCode 7.3上运行它。

更新:仍在XCode 9.2 / Swift 4中

1 个答案:

答案 0 :(得分:0)

这是因为Testp可以很容易地是classstruct。如果是struct,那么分配testContainer.test.notes = "y"将创建Testp实施者的全新实例。另一方面,通过制作protocol Testp: class,您明确告知notes的作业不会更改test

考虑一个函数

func doSomething(_ container: TestContainer) {
    testContainer.test.notes = "y"
}

在这个函数中你不知道如何使用类或结构配置TestContainer。我想迅速的团队认为总是提高will/didChange就不那么容易混淆了这种情况。