Property Observers

A portrait painting style image of a pirate holding an iPhone.

by The Captain

on
May 15, 2023

Using Property Observers in Swift

Property observers provide a way to respond to changes in the values of properties of a class, struct or enumeration. They enable you to run some custom code before or after the value of a property changes. Property observers are available for stored and computed properties. Let's take a look at how property observers are used in Swift with the following code snippet:

class Account {
    var balance: Double {
        willSet(newBalance) {
            print("About to change balance from \(balance) to \(newBalance)")
        }
        didSet {
            print("Balance changed from \(oldValue) to \(balance)")
        }
    }
    
    init(balance: Double) {
        self.balance = balance
    }
}

var myAccount = Account(balance: 1000)
myAccount.balance = 2000 // Output: "About to change balance from 1000.0 to 2000.0" and "Balance changed from 1000.0 to 2000.0"

Here, we have defined a class named `Account` which has a stored property named `balance`. The `willSet` block is executed just before the stored property's value is set to the new value. In this case, it is used to print a message that describes the old and new values of the `balance` property. The `didSet` block is executed just after the stored property's value has been set with the new value. In this case, it is used to print a message that describes the old and new values of the `balance` property.

We can also use these property observers in computed properties, which allows us to execute some custom code whenever their values change.

struct Temperature {
    var celcius: Double {
        willSet {
            print("About to change temperature from \(celcius)℃ to \(newValue)℃")
        }
        didSet {
            if celcius > oldValue {
                print("Temperature has increased by \(celcius - oldValue)℃")
            } else if celcius < oldValue {
                print("Temperature has decreased by \(oldValue - celcius)℃")
            }
        }
    }
    
    init(celcius: Double) {
        self.celcius = celcius
    }
}

var currentTemperature = Temperature(celcius: 20.0)
currentTemperature.celcius = 25.0
// Output: "About to change temperature from 20.0℃ to 25.0℃" and "Temperature has increased by 5.0℃"

In this example, we have a computed property named `celcius` in our struct `Temperature`. We have implemented the `willSet` and `didSet` property observers to print a message that describes the old and new temperature values. The `didSet` block is also used to print a message that describes whether the temperature has increased or decreased and by how much amount.

Summary