Property observers willSet and didSet; Property getters and setters

@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.


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


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

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'