东东

Swift细节之willSet和didSet执行
willSet和didSet是swift中的属性观察者,可用于存储属性修改时的操作。关于计算属性和存储属性可以查看...
扫描右侧二维码阅读全文
24
2019/09

Swift细节之willSet和didSet执行

willSetdidSet是swift中的属性观察者,可用于存储属性修改时的操作。关于计算属性存储属性可以查看这个文章:从一个报错说下Swift计算属性和存储属性

willSet 观察器会将新的属性值作为常量参数传入,在 willSet 的实现代码中可以为这个参数指定一个名称,如果不指定则参数仍然可用,这时使用默认名称 newValue 表示。

同样,didSet 观察器会将旧的属性值作为参数传入,可以为该参数指定一个名称或者使用默认参数名 oldValue。如果在 didSet 方法中再次对该属性赋值,那么新值会覆盖旧的值。

初始化过程不会被调用

在用的时候可能会发现某种情况下willSet和didSet不被调用,这是因为文档中提过

当一个属性首次初始化时,willSet和didSet观察者不会被调用。只有在属性值设置在初始化上下文之外时才会调用它们。

所以如果你是在初始化中这样写的,那么是不会执行的

    var mIconImage:UIImage = UIImage(named: "cell_weather")! {
        willSet {
            self.mIconImageView.image = newValue
        }
    }
    
    var mTitleText : String = "" {
        willSet {
            self.mTitleLabel.text = newValue
        }
    }
    
    convenience init(iconImage:UIImage, titleText:String) {
        self.init(frame: CGRect.zero)
        self.mIconImage = iconImage
        self.mTitleText = titleText
    }

初始化强制调用

如果想要强制这个在初始化过程中调用呢,那么可以使用defer延迟声明,也可以使用自定义函数,这两种方案都可行

1、使用defer关键词

    var mIconImage:UIImage = UIImage(named: "cell_weather")! {
        willSet {
            self.mIconImageView.image = newValue
        }
    }
    
    var mTitleText : String = "" {
        willSet {
            self.mTitleLabel.text = newValue
        }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.p_createUI()
    }
    
    convenience init(iconImage:UIImage, titleText:String) {
        self.init(frame: CGRect.zero)
        defer {
            self.mIconImage = iconImage
            self.mTitleText = titleText
        }
    }

2、构造一个赋值的函数,在函数中调用

    var mIconImage:UIImage = UIImage(named: "cell_weather")! {
        willSet {
            self.mIconImageView.image = newValue
        }
    }
    
    var mTitleText : String = "" {
        willSet {
            self.mTitleLabel.text = newValue
        }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.p_createUI()
    }
    
    convenience init(iconImage:UIImage, titleText:String) {
        self.init(frame: CGRect.zero)
        self.p_loadData(iconImage: iconImage, titleText: titleText)
    }
    
    func p_loadData(iconImage:UIImage, titleText:String) -> Void {
        self.mIconImage = iconImage
        self.mTitleText = titleText
    }

至于网上的通过KVC方法赋值后,再添加setValueforUndefinedKey方法做特殊处理的方案就不要采用了

Last modification:September 24th, 2019 at 11:22 am
如果觉得我的文章对你有用,请随意打赏: ☞已打赏列表

2 comments

  1. 官仁有话说

    好高端,完全看不懂哈哈哈

    1. 东东
      @官仁有话说

      用来搬砖的工具而已

Leave a Comment