Property observers willSet and didSet; Property getters and setters

SwiftPropertiesDidsetProperty Observer

Swift Problem Overview


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

From my point of view, both of them can set a value for a property. When, and why, should I use willSet - didSet, and when get - set?

I know that for willSet and didSet, the structure looks like this:

var variable1 : Int = 0 {
    didSet {
        println (variable1)
    }
    willSet(newValue) {
    ..
    }
}

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

Swift Solutions


Solution 1 - Swift

>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'

Solution 2 - Swift

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

Solution 3 - Swift

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][1]
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][2] this is different concept.) [1]: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html [2]: https://vishal-singh-panwar.github.io/SwiftProtocols/


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

Solution 4 - Swift

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

Solution 5 - Swift

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionjust MEView Question on Stackoverflow
Solution 1 - SwiftMaxim ShoustinView Answer on Stackoverflow
Solution 2 - SwiftAntonioView Answer on Stackoverflow
Solution 3 - SwiftNiravSView Answer on Stackoverflow
Solution 4 - SwiftJackView Answer on Stackoverflow
Solution 5 - SwiftAndy JazzView Answer on Stackoverflow