Getting property changing notifications using property observers
It’s common to want to know when a property’s value changes. Perhaps you want to update the value of another property or update some UI element. In Objective-C, this was often accomplished by writing your own getter and setter or using Key-Value Observing (KVO). However, in Swift, we have native support for property observers.
Getting ready
To examine property observers, we should create an object with a property that we want to observe. Let’s create an object that manages users and a property that holds the current user’s name.
Enter the following code into a new playground:
class UserManager { var currentUserName: String = "Emmanuel Goldstein" }
We want to present some friendly messages when the current user changes. We’ll use property observers to do this.
How to do it...
Let’s get started:
- Amend the
currentUserName
property definition so that it looks as follows:class UserManager { var currentUserName: String = "Guybrush Threepwood" { willSet (newUserName) { print("Goodbye to \(currentUserName)") print("I hear \(newUserName) is on their way!") } didSet (oldUserName) { print("Welcome to \(currentUserName)") print("I miss \(oldUserName) already!") } } }
- Create an instance of
UserManager
, and change the current username. This will generate friendly messages:let manager = UserManager() manager.currentUserName = "Elaine Marley" // Goodbye to Guybrush Threepwood // I hear Elaine Marley is on their way! // Welcome to Elaine Marley // I miss Guybrush Threepwood already! manager.currentUserName = "Ghost Pirare LeChuck" // Goodbye to Elaine Marley // I hear Ghost Pirare LeChuck is on their way! // Welcome to Ghost Pirare LeChuck // I miss Elaine Marley already!
How it works...
Property observers can be added within curly brackets after the property declaration, and there are two types – willSet
and didSet
.
The willSet
observer will be called before the property is set and provides the value that will be set on the property. This new value can be given a name within brackets – for example, newUserName
:
willSet (newUserName) { //... }
The didSet
observer will be called after the property is set and provides the value that the property had before being set. This old value can be given a name within brackets – for example, oldUserName
:
didSet (oldUserName) { //... }
There’s more...
The new value and old value that are passed into the property observers have implicit names, so there is no need to explicitly name them. The willSet
observer is passed a value with an implicit name of newValue
, and the didSet
observer is passed a value with an implicit name of oldValue
.
Therefore, we can remove our explicit names and use the implicit value names:
class UserManager { var currentUserName: String = "Guybrush Threepwood" { willSet { print("Goodbye to \(currentUserName)") print("I hear \(newValue) is on their way!") } didSet { print("Welcome to \(currentUserName)") print("I miss \(oldValue) already!") } } }
See also
Further information about property observers can be found in Apple’s documentation on the Swift language at http://swiftbook.link/docs/properties.