Property observers in Swift allow you to respond to changes in a property's value. This concept was introduced with Swift to enhance the transparency of data change control and to automate logic during changes.
Background:
Before Swift, such behavior was often implemented manually through setters or special methods. In Swift, observers were introduced as a standard tool in the language.
Problem:
It's important for developers to be able to detect the moment a property changes — for example, to update the UI or validate data. Without observers, the code would become bulkier and less readable.
Solution:
Swift provides two main observers:
willSet is called before the value changesdidSet is called after a new value is assignedObservers can be added to stored properties, excluding lazy properties and computed properties.
Code example:
class Temperature { var celsius: Double { willSet { print("A new value will be set", newValue) } didSet { print("The old value was:", oldValue, ", and now it is:", celsius) } } init(celsius: Double) { self.celsius = celsius } } let temp = Temperature(celsius: 22) temp.celsius = 28 // will print willSet and didSet
Key features:
Can observers be added to computed properties?
No, willSet and didSet cannot be added to computed properties, as they already have their own getter and setter. Using willSet/didSet is only relevant for stored properties.
Will observers be called when changing a property inside the initializer?
No, property observers are not called during initialization (init). They are triggered only when the value changes after the init is completed.
What happens when assigning the current value to itself, for example x = x?
The observers will still be called even if the property's value has not changed! This can lead to side effects in the logic — be careful.
var value: Int = 0 { didSet { print("didSet is always called!") } } value = value // didSet will be called
A developer implemented UI updates in didSet but did not check for value changes. The UI was updated even during "empty" assignments, which reduced performance.
Pros:
Cons:
In didSet, equality between old and new values was checked. The interface was updated only if the value genuinely changed.
Pros:
Cons: