Swift5 didSet willSet set get

属性

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 中变量的使用细节

你可能感兴趣的:(Swift5 didSet willSet set get)