Swift的属性声明语法与c#非常相似:

var foo: Int {
    get { return getFoo() }
    set { setFoo(newValue) }
}

但是,它也有willSet和didSet动作。它们分别在调用setter之前和之后调用。考虑到在setter中可以有相同的代码,它们的目的是什么?


当前回答

didSet非常方便的一件事是当您使用outlet添加额外配置时。

@IBOutlet weak var loginOrSignupButton: UIButton! {
  didSet {
        let title = NSLocalizedString("signup_required_button")
        loginOrSignupButton.setTitle(title, for: .normal)
        loginOrSignupButton.setTitle(title, for: .highlighted)
  }

其他回答

didSet非常方便的一件事是当您使用outlet添加额外配置时。

@IBOutlet weak var loginOrSignupButton: UIButton! {
  didSet {
        let title = NSLocalizedString("signup_required_button")
        loginOrSignupButton.setTitle(title, for: .normal)
        loginOrSignupButton.setTitle(title, for: .highlighted)
  }

您还可以使用didSet将变量设置为不同的值。这不会像属性指南中所述的那样导致再次调用观察者。例如,当你想限制值如下所示时,它是有用的:

let minValue = 1

var value = 1 {
    didSet {
        if value < minValue {
            value = minValue
        }
    }
}

value = -10 // value is minValue now.

我不懂c#,但稍微猜一下,我想我懂了

foo : int {
    get { return getFoo(); }
    set { setFoo(newValue); }
}

所做的事。它看起来非常类似于你在Swift中拥有的,但它不一样:在Swift中你没有getFoo和setFoo。这不是一个小的区别:这意味着你没有任何底层存储你的价值。

Swift已经存储和计算了属性。

计算属性有get,也可能有set(如果它是可写的)。但是getter和setter中的代码,如果它们需要实际存储一些数据,就必须在其他属性中完成。没有备份存储。

另一方面,存储属性确实有备份存储。但是它没有get和set。相反,它有willSet和didSet,你可以使用它们来观察变量的变化,并最终触发副作用和/或修改存储的值。对于计算属性,您没有willSet和didSet,并且您不需要它们,因为对于计算属性,您可以使用set中的代码来控制更改。

请注意 当在委托发生之前在初始化式中设置属性时,不会调用willSet和didSet观察器

重点似乎是,有时您需要一个具有自动存储和某些行为的属性,例如通知其他对象该属性刚刚更改。当您只有get/set时,您需要另一个字段来保存该值。使用willSet和didSet,您可以在修改值时采取行动,而不需要另一个字段。例如,在这个例子中:

class Foo {
    var myProperty: Int = 0 {
        didSet {
            print("The value of myProperty changed from \(oldValue) to \(myProperty)")
        }
    }
}

每次修改myProperty时,都会打印它的旧值和新值。只有getter和setter,我需要这个代替:

class Foo {
    var myPropertyValue: Int = 0
    var myProperty: Int {
        get { return myPropertyValue }
        set {
            print("The value of myProperty changed from \(myPropertyValue) to \(newValue)")
            myPropertyValue = newValue
        }
    }
}

因此,willSet和didSet代表了两行代码的节省,并且字段列表中的噪音更少。