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 user interface element. In Objective-C, this was often accomplished by writing your own getter and setter or using Key-Value Observing (KVO), but 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:
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 = "Emmanuel Goldstein" {
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 = "Dade Murphy"
// Goodbye to Emmanuel Goldstein
// I hear Dade Murphy is on their way!
// Welcome to Dade Murphy
// I miss Emmanuel Goldstein already!
manager.currentUserName = "Kate Libby"
// Goodbye to Dade Murphy
// I hear Kate Libby is on their way!
// Welcome to Kate Libby
// I miss Dade Murphy 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 = "Emmanuel Goldstein" {
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.