willSet and didSet in Swift

willSet and didSet in Swift

In Swift, willSet and didSet are called property observers. They are used to observe and respond to changes in property values. These observers are attached to properties and are triggered when the value of the property is about to be set (willSet) or has just been set (didSet).

Here's a brief explanation of willSet and didSet in Swift:

willSet: This observer is called just before the value of the property is set. It provides you with the new value as a default parameter (newValue). You can use this to perform actions before the new value is assigned.

The willSet observer is executed just before the value of the property is set. Here are some key points to remember:

  1. Access to newValue: Inside the willSet block, you have access to a special parameter called newValue, which represents the new value that is about to be assigned to the property.
var myProperty: Int = 0 {
    willSet {
        print("About to set myProperty to \(newValue)")
    }
}
  1. Omitting newValue: If you don't need to use the newValue parameter inside the willSet block, you can omit it altogether:
var myProperty: Int = 0 {
    willSet {
        print("About to set myProperty")
    }
}
  1. No Change Allowed: You cannot change the value of the property inside the willSet observer. Attempting to assign a value to the property within willSet will result in a compiler error.

didSet: This observer is called immediately after the value of the property is set. It provides you with the old value of the property as a default parameter (oldValue). You can use this to perform actions after the new value has been assigned.

The didSet observer is executed immediately after the value of the property is set. Here's what you need to know about didSet:

  1. Access to oldValue: Inside the didSet block, you have access to a special parameter called oldValue, which represents the previous value of the property.
var myProperty: Int = 0 {
    didSet {
        print("myProperty was set to \(myProperty), previously it was \(oldValue)")
    }
}
  1. Omitting oldValue: If you don't need to use the oldValue parameter inside the didSet block, you can omit it altogether:
var myProperty: Int = 0 {
    didSet {
        print("myProperty was set to \(myProperty)")
    }
}
  1. Property Changes: You can change other properties within the didSet observer, including the property itself. However, be cautious with infinite loops or unintended side effects.

Example Use Cases

Here are some common scenarios where property observers are useful:

  • Validation: You can use willSet to validate incoming values before assigning them to properties.
  • UI Updates: You can use didSet to update UI elements based on property changes.
  • Logging: Property observers are handy for logging property changes for debugging purposes.
  • Caching: You can use didSet to update a cache or trigger cache invalidation when a property changes.
var age: Int = 0 {
    didSet {
        if age < 0 {
            print("Age cannot be negative. Resetting to 0.")
            age = 0
        }
    }
}

In this example, the didSet observer ensures that the age property is never negative, resetting it to 0 if a negative value is assigned.

Overall, property observers provide a powerful mechanism for reacting to changes in property values, enabling you to encapsulate logic related to property changes directly within your types. These property observers are useful for executing code in response to changes in property values, such as updating UI elements, triggering side effects, or maintaining consistency between related properties.