属性
Swift 中的属性分为存储型属性(stored variable)和计算型属性(computed variable)。
存储型属性,顾名思义, 就是我们一般意义上理解的可以进行赋值和取值的变量。
var number: Int = 10
计算型属性, 字面意思为"计算型的属性", 虽然也叫"属性", 但要注意, 这个家伙是根本没法存储值的。
计算型属性
特征:仅有 get(可省,readOnly语义) 或 有 get + set 的属性是计算型属性
有 get + set 的属性仅作为其他属性的外部接口
- 计算型属性本身不占用内存空间,所以不可赋值
get + set 为计算型属性的原因:
真正赋值的过程是存在于 set 方法中并被底层包装掉的,如果我们手动实现了 set 方法,就无法进行正确赋值:

get + set 的正确使用方法:作为其他属性的外部接口
class PositiveNumber {
private var _value: Double = 0.0
var value: Double {
get {
return _value
}
set {
if (newValue <= 0) {
print("赋值不合理!")
} else {
_value = newValue
}
}
}
}
存储型属性
注意:初始化方法生成对象,并不会触发属性的 willSet didSet 方法。
若想在初始化阶段触发 didSet,可以采用 KVC 的方式给对象初始化
willSet 能获取将要赋给属性的值 newValue
- 操作的属性是对旧值操作,会被之后的内部 set 覆盖掉
- 作用:观察
didSet 能获取属性之前的旧值 oldValue,新值即为属性
- 操作属性是对新值进行操作
- 作用:观察、数据加工
- 当使用了 didSet 就不能再使用 set 了,因为 didSet 中已经包含了 set 状态
class PositiveNumber {
var value: Double {
willSet {
print("willSet 方法被调用")
print("在 willSet 中, value = \(value), newValue = \(newValue)")
}
didSet {
print("didSet 方法被调用")
print("在 didSet 中, value = \(value), oldValue = \(oldValue)")
}
}
init(value: Double) {
self.value = value
}
}
初始化方法生成对象,并不会触发属性的 willSet didSet 方法:
// 初始化方法 不会触发 willSet didSet
let number = PositiveNumber(value: 10.0)
改用 KVC 的方式给对象初始化,就可以调用didSet了:
- 改造:继承 NSObject 重新构造函数、属性前加 @objc、属性变为必选类型并给默认值
class PositiveNumber: NSObject {
@objc var value: Double = 0 {
willSet {
print("willSet 方法被调用")
print("在 willSet 中, value = \(value), newValue = \(newValue)")
}
didSet {
print("didSet 方法被调用")
print("在 didSet 中, value = \(value), oldValue = \(oldValue)")
}
}
init(value: Double) {
super.init()
setValue(value, forKey: "value")
}
}
// 此时再初始化对象就可以触发方法了
let number = PositiveNumber(value: 10.0)
//willSet 方法被调用
//在 willSet 中, value = 0.0, newValue = 10.0
//didSet 方法被调用
//在 didSet 中, value = 10.0, oldValue = 0.0
计算型属性与懒加载
计算型属性:只是为了调用其他属性而包装的读取方法

- 不分配独立的存储空间
- 每次调用时都会被执行
var title: String {
return "Mr" + (name ?? "")
}
懒加载属性
- 在第一次调用时,执行闭包并且分配空间存储闭包返回的数值
- 会分配独立的存储空间
- 与 OC 不同的是,lazy 属性即使被设置为 nil 也不会被再次调用
lazy var title: String = {
return "Mr " + (self.name ?? "")
}()
参考资料:
Swift 中变量的使用细节