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:
- Access to newValue: Inside the
willSet
block, you have access to a special parameter callednewValue
, 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)")
}
}
- Omitting newValue: If you don't need to use the
newValue
parameter inside thewillSet
block, you can omit it altogether:
var myProperty: Int = 0 {
willSet {
print("About to set myProperty")
}
}
- No Change Allowed: You cannot change the value of the property inside the
willSet
observer. Attempting to assign a value to the property withinwillSet
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
:
- Access to oldValue: Inside the
didSet
block, you have access to a special parameter calledoldValue
, which represents the previous value of the property.
var myProperty: Int = 0 {
didSet {
print("myProperty was set to \(myProperty), previously it was \(oldValue)")
}
}
- Omitting oldValue: If you don't need to use the
oldValue
parameter inside thedidSet
block, you can omit it altogether:
var myProperty: Int = 0 {
didSet {
print("myProperty was set to \(myProperty)")
}
}
- 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.