Property observers willSet and didSet; Property getters and setters

前端 未结 5 1731
孤城傲影
孤城傲影 2020-12-07 17:22

What is the difference between willSet - didSet, and get - set, when working with this inside a property?

From my

相关标签:
5条回答
  • 2020-12-07 18:07

    get set:

    get set are Computed Properties Which do not actually store a value. Instead, they provide a getter and an optional setter to retrieve and set other properties and values indirectly

    Additionally you can define Read-Only Computed Properties. A read-only computed property always returns a value, and can be accessed through dot syntax, but cannot be set to a different value

    Example get only property-

     var number: Double {
            return .pi*2
        }
    

    willSet didSet:

    willSet didSet are Property Observers

    Property observers observe and respond to changes in a property’s value. Property observers are called every time a property’s value is set, even if the new value is the same as the property’s current value.

    • willSet is called just before the value is stored.
    • didSet is called immediately after the new value is stored.

    Example -

    var score: Int = 0 {
        willSet(newScore) {
            print("willSet  score to \(newScore)")
        }
        didSet {
            print("didSet score to \(oldValue) new score is: \(score)")
        }
    }
    score = 10
    //Output 
    //willSet  score to 10
    //didSet score to 0 new score is: 10
    

    https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html

    0 讨论(0)
  • 2020-12-07 18:19
    var variable1 : Int = 0 { //It's a store property
        didSet {
            print (variable1)
        }
        willSet(newValue) {
        ..
        }
    }
    
    var variable2: Int { //It's a Computed Proprties
        get {
            return variable2
        }
        set (newValue){
        }
    }
    

    For detail info of Store property and computed property
    So when you are trying to assign the value into variable at that assigning time come the concept of 'didSet' & 'willSet'. As @Maxim says

    • willSet is called just before the value is stored.
    • didSet is called immediately after the new value is stored.


    Example of 'willSet' & 'didSet' :

    class Number {
       var variable1 : Int = 0 {
            didSet{
                print("didSet called")
            }
            willSet(newValue){
                print("willSet called")
            }
    
        }
    }
    print("we are going to add 3")
    Number().variable1 = 3
    print("we added 3")
    

    //o/p:
    we are going to add 3
    willSet called
    didSet called
    we added 3

    And generally when two property are dependent at that time 'get' & 'set' used. (It's also used in protocol this is different concept.)

    Example of 'get' & 'set':

    class EquilateralTriangle{
        var sideLength: Double = 0.0
        init(sideLength: Double){
            self.sideLength = sideLength
        }
        var perimeter: Double {
            get {
                return 3.0 * sideLength
            }
            set {
                sideLength = newValue / 3.0
            }
        }
    
    }
    
    var triangle = EquilateralTriangle(sideLength: 3.0)
    print(triangle.perimeter) //o/p: 9.0
    triangle.perimeter = 12.0
    print(triangle.sideLength) //o/p: 4.0
    
    0 讨论(0)
  • 2020-12-07 18:20

    @Maxim's answer is for the 1st part of your question.

    As for when to use get and set: when you want a computed property. This:

    var x: Int
    

    creates a stored property, which is automatically backed up by a variable (not directly accessible though). Setting a value to that property is translated in setting the value in the property, and similarly for getting.

    Instead:

    var y = {
        get { return x + 5 }
        set { x = newValue - 5}
    }
    

    will create a computed property, which is not backed up by a variable - instead you have to provide the implementation of the getter and/or setter, usually reading and writing values from another property and more generally as a result of a computation (hence the computed property name)

    Suggested reading: Properties

    Note: your code:

    var variable2: Int {
        get{
            return variable2
        }
        set (newValue){
        }
    }
    

    is wrong because in the get you are trying to return itself, which means calling get recursively. And in fact the compiler will warn you with a message like Attempting to access 'variable2' within its own getter.

    0 讨论(0)
  • 2020-12-07 18:22

    When and why should I use willSet/didSet

    • willSet is called just before the value is stored.
    • didSet is called immediately after the new value is stored.

    Consider your example with outputs:


    var variable1 : Int = 0 {
            didSet{
                print("didSet called")
            }
            willSet(newValue){
                print("willSet called")
            }
        }
    
        print("we are going to add 3")
    
         variable1 = 3
    
        print("we added 3")
    

    Output:

    we are going to add 3
    willSet called
    didSet called
    we added 3
    

    it works like pre/post -condition

    On the other hand, you can use get if you want to add, for example, a read-only property:

    var value : Int {
     get {
        return 34
     }
    }
    
    print(value)
    
    value = 2 // error: cannot assign to a get-only property 'value'
    
    0 讨论(0)
  • 2020-12-07 18:23

    get set

    You can use a regular get-and-set syntax in case you want to implement gettable and settable property. However, you may use just get syntax in case you implement read-only property. With setter you are given a newValue property.

    class GetterSetter {
        var theValue: Bool = false
        var property: Bool {
            get { return theValue }
            set {
                print("Value changed from \(theValue) to \(newValue)")
                theValue = newValue
            }
        }
    }
    
    let getterSetter = GetterSetter()
    getterSetter.property = true
    getterSetter.property
    
    // PRINTS:
    // Value changed from 'false' to 'true'
    

    didSet

    didSet property observer is used in case we need to execute a code when a property has just been set. Implementing didSet you are given oldValue to represent the previous value.

    class DidSetter {
        var property: Float16 = -1.0 {
            didSet {
                print("Value changed from \(oldValue) to \(property)")
            }
        }
    }
    
    let didSetter = DidSetter()
    didSetter.property = 5.0
    didSetter.property
    
    // PRINTS:
    // Value changed from -1.0 to 5.0
    

    willSet

    willSet property observer is used in case we need to execute a code before a property has been set. Implementing willSet you are given newValue to represent the new property value that it's going to be.

    class WillSetter {
        var property: String = "NO" {
            willSet {
                print("Value changed from \(property) to \(newValue)")
            }
        }
    }
    
    let willSetter = WillSetter()
    willSetter.property = "YES"
    willSetter.property
    
    // PRINTS:
    // Value changed from NO to YES
    
    0 讨论(0)
提交回复
热议问题