我观察到那些我不太了解的行为。在操场上执行此代码时:
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"
如上所述,即使未设置属性本身,也会调用willSet
和didSet
块。
另一方面,如果我将协议更改为类型类,如下所示
protocol Testp: class {
var notes: String { get set }
}
然后结果就像我预期的那样(即没有调用willSet/didSet
)。
这种行为的原因是什么?
我在XCode 7.3上运行它。
更新:仍在XCode 9.2 / Swift 4中
答案 0 :(得分:0)
这是因为Testp
可以很容易地是class
或struct
。如果是struct
,那么分配testContainer.test.notes = "y"
将创建Testp
实施者的全新实例。另一方面,通过制作protocol Testp: class
,您明确告知notes
的作业不会更改test
。
考虑一个函数
func doSomething(_ container: TestContainer) {
testContainer.test.notes = "y"
}
在这个函数中你不知道如何使用类或结构配置TestContainer
。我想迅速的团队认为总是提高will/didChange
就不那么容易混淆了这种情况。