【问题标题】:Can we use willSet and didSet with getter and setter?我们可以将 willSet 和 didSet 与 getter 和 setter 一起使用吗?
【发布时间】:2017-08-20 09:49:06
【问题描述】:

我正在阅读有关 swift 中的 willset 和 didset 属性的信息 我开始知道我可以将这些与具有如下初始值的变量一起使用:

var property = "name"
{
    willSet
    {
        print("property is about to changed")
    }
    didSet
    {
        if property == oldValue
        {
            print("values are same")
        }
        else
        {
            print("value changed")
        }
    }
}

property = "anothername"

我可以像下面这样使用 willget 和 didset:

var property2:String{

    willSet
    {
        print("value is about to change")
    }
    didSet
    {
        print("value is changes")
    }
}

它给了我这个错误:

non-member observing properties require an initializer
var property2:String{
    ^

所以任何人都可以向我解释这里发生了什么,我可以将 getter 和 setter 与 willset 和 didset 一起使用,例如:

var property2:String{

    get{return property2}
    set{propert2 = newValue}

    willSet
    {
        print("value is about to change")
    }
    didSet
    {
        print("value is changes")
    }
}

【问题讨论】:

    标签: swift properties getter-setter


    【解决方案1】:

    你可以通过给属性一个默认值来解决你缺少初始化器的错误,就像你的第一段代码所做的那样:

    var property2:String = "Some default value"{
    
        willSet
        {
            print("value is about to change")
        }
        didSet
        {
            print("value is changes")
        }
    }
    

    现在我将回答为什么不能在计算属性上使用属性观察器。

    因为没有意义。

    对于一个可设置的计算属性,你已经有了setter,所以你可以编写任何你想在设置值时执行的代码在setter中。为什么需要额外的willSetdidSet?而对于一个只获取计算的属性,它不能被设置,所以你希望willSetdidSet 什么时候被执行?

    基本上,计算属性中的set 块已经实现了willSetdidSet 的目的。您在willSet 中写入的所有内容都可以在设置值之前将其写入set。在didSet 中写入的所有内容都可以在设置值后写入set

    另外,请注意,您的第三个代码可能会导致堆栈溢出,因为您在自己的 getter 中访问 property2 并将其设置在自己的 setter 中。

    【讨论】:

      【解决方案2】:
      • 第一期(第二期):

        属性/成员没有初始值,这就是错误消息所说的,您需要编写一个初始化程序或像第一个 sn-p 一样分配一个初始值。该错误与观察者无关。

      • 第二期(第三期):

        不允许在计算属性中使用属性观察器。没有观察者的示例无论如何都不起作用(假设propert2 是一个错字,你的意思是property2)。 setter 会导致无限循环,因为它正在调用自己。

      【讨论】:

        【解决方案3】:

        来自 Apple Doc 类和结构必须在创建该类或结构的实例时将其所有存储的属性设置为适当的初始值。存储的属性不能处于不确定状态。

        所以你可以通过添加来解决这个问题? var property2:String?{

        var property2:String?{
        
            willSet
            {
                print("value is about to change")
            }
            didSet
            {
                print("value is changes")
            }
        }
        

        【讨论】:

        • 无意冒犯,但最糟糕的建议是替换为缺少的初始值设定项。
        • 嘿@vadian 你介意解释一下为什么这是一个坏建议吗?我不怀疑,我只是不知道。
        猜你喜欢
        • 2023-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多