在 Swift 中所声明的属性包括存储属性和计算属性两种。其中存储属性将会在内存中实际分配地址对属性进行存储,而计算属性则不包括背后的存储,只是提供 set 和 get 两种方法。在同一个类型中,属性观察和计算属性是不能同时共存的。也就是说,想在一个属性定义中同时出现 set 和 willSet 或 didSet 是一件办不到的事情。计算属性中我们可以通过改写 set 中的内容来达到和 willSet 及 didSet 同样的属性观察的目的。如果我们无法改动这个类,又想要通过属性观察做一些事情的话,可能就需要子类化这个类,并且重写它的属性了。重写的属性并不知道父类属性的具体实现情况,而只从父类属性中继承名字和类型,因此在子类的重载属性中我们是可以对父类的属性任意地添加属性观察的,而不用在意父类中到底是存储属性还是计算属性:
case1
class A {
var number :Int {
get {
print("get")
return 1
}
set {print("set")}
}
}
class B: A {
override var number: Int {
willSet {print("willSet")}
didSet {print("didSet")}
}
}
//调用 number 的 set 方法可以看到工作的顺序
let b = B()
b.number = 0
// 输出
// get // 这个输出是为了获取odlValue
// willSet
// set
// didSet
case2
class A {
var number :Int = 0 {
willSet {print("willSet")}
didSet {print("didSet")}
}
}
class B: A {
override var number: Int {
get {
print("get")
return 1
}
set {print("set")}
}
}
//调用 number 的 set 方法可以看到工作的顺序
let b = B()
b.number = 0
b.number
// 输出
// set
// get
case3
class A {
var number :Int = 0 {
willSet {print("willSet")}
didSet {print("didSet")}
}
}
class B: A {
override var number: Int {
get {
print("get")
return super.number
}
set {
print("set")
super.number = newValue
}
}
}
//调用 number 的 set 方法可以看到工作的顺序
let b = B()
b.number = 0
b.number
// 输出
//set
//willSet
//didSet
//get
case4
class A {
var number :Int = 0 {
willSet {print("willSet")}
didSet {print("didSet")}
}
}
class B: A {
override var number: Int {
willSet {print("willSet_b")}
didSet {print("didSet_b")}
}
}
//调用 number 的 set 方法可以看到工作的顺序
let b = B()
b.number = 0
b.number
// 输出
//willSet_b
//willSet
//didSet
//didSet_b
1.当计算属性被override为存储属性时相当于为set方法添加了 willSet 和didSet 方法
2.当存储属性被override为计算属性时会忽略 willSet 和didSet 方法
3.当调用super时,调用顺序便可控制