- API fetch
- Array
- Async await
- Class
- Closures
- Computed property
- Concurrency
- Constants
- Data types
- Defer statement
- Dictionary
- Enum
- Escaping closure
- Extension
- For loop
- forEach
- Function
- Generics
- Guard statement
- if let statement
- Inheritance
- inout
- Lazy var
- Operator
- Optionals
- Property observers
- Property wrapper
- Protocol
- String formatting
- String interpolation
- Struct
- Switch statement
- Try catch
- Tuple
- Variables
- While loop
SWIFT
Swift Property Observers: Syntax, Use Cases, and Best Practices
Swift property observers
let you monitor and respond to changes in property values. These observers run custom code before or after a property’s value is modified. You typically use property observers in Swift to trigger actions like updating UI, logging changes, validating data, or synchronizing state across objects.
Unlike computed properties, property observers apply to stored properties—those that hold actual values—and are executed during assignment, even if the new value is the same as the old one.
Syntax of Property Observers in Swift
There are two types of property observers Swift
supports:
willSet
: Executes just before the value is set. It provides access to the new value.didSet
: Executes right after the value is set. It provides access to the previous value.
Here's an example of both:
var score: Int = 0 {
willSet {
print("Score will change from \(score) to \(newValue)")
}
didSet {
print("Score changed from \(oldValue) to \(score)")
}
}
Assigning a new value will trigger both observers:
score = 10
// Output:
// Score will change from 0 to 10
// Score changed from 0 to 10
You can omit one of the two if it's not needed.
The newValue
and oldValue
Keywords
In the willSet
block, Swift provides a newValue
variable, which represents the value that’s about to be assigned. You can rename it for clarity:
willSet(newScore) {
print("Preparing to set new score: \(newScore)")
}
In the didSet
block, oldValue
refers to the property’s value before it was changed. These implicit variables allow you to compare, react, and perform differential updates.
Applying Observers to Stored Properties
You can use Swift property observers
with stored properties in both classes and structs:
struct Temperature {
var celsius: Double {
didSet {
print("Celsius updated to \(celsius)")
}
}
}
Each time celsius
changes, the didSet
block is called. This is especially useful when state changes need to ripple through related components.
Use Cases for Property Observers in Swift
Property observers Swift
developers use serve many practical purposes:
UI Updates
You can update a UI element in response to data changes.
var username: String = "" {
didSet {
nameLabel.text = username
}
}
Logging Changes
var loggedIn: Bool = false {
didSet {
print("User login state changed: \(loggedIn)")
}
}
Input Validation
var quantity: Int = 1 {
didSet {
if quantity < 1 {
quantity = 1
}
}
}
In this case, setting an invalid value automatically corrects it.
State Synchronization
Observers help keep two related properties in sync:
var userID: Int = 0 {
didSet {
fetchUserDetails(for: userID)
}
}
Property Observers with Optionals
You can use property observers with optional properties, and they will still be triggered when the value changes:
var token: String? {
didSet {
print("Auth token updated.")
}
}
Setting it to nil
or assigning a new token triggers the observer.
Observers in Class Inheritance
Observers don’t get inherited by subclasses. If you subclass a class with property observers, the subclass must explicitly redefine the property to observe changes.
class Base {
var name: String = "" {
didSet {
print("Base updated name")
}
}
}
class Child: Base {
// If you want the observer here, you must override it
override var name: String {
didSet {
print("Child updated name")
}
}
}
Without the override, the Child
class won't inherit the observer.
Property Observers and Initializers
Observers are not called during property initialization in the same scope. That means when a property is set as part of the object’s own initialization, observers don’t run.
var message: String = "Hello" {
didSet {
print("Message changed")
}
}
init() {
message = "Welcome" // didSet is NOT triggered here
}
However, if a superclass sets a property on a subclass with observers, those observers do get triggered.
Observers with Static Properties
You can’t add observers to static (type-level) stored properties directly. Swift only allows observers on instance properties.
static var count: Int = 0 // ❌ Can't observe this
As a workaround, use computed properties with manual logic if you need change tracking for static values.
Differences Between Property Observers and Computed Properties
It’s important to understand how Swift property observers
differ from computed properties:
- A computed property recalculates its value every time you access it and does not store data.
- A stored property with observers keeps its value in memory and runs additional logic on assignment.
Example:
// Computed property
var isAdult: Bool {
return age >= 18
}
// Stored property with observers
var age: Int = 0 {
didSet {
print("Age updated")
}
}
Use property observers when you want to monitor actual data changes; use computed properties when the value is derived.
Nesting Observers in Property Wrappers
You can combine property observers Swift
patterns with property wrappers like @Published
or @State
in SwiftUI. However, once wrapped, you can't use willSet
or didSet
directly on the property. Instead, you must observe changes in other ways, like via onChange
or Combine publishers.
Avoiding Common Pitfalls
Some best practices when using Swift property observers:
- Avoid infinite loops: If
didSet
modifies the same property again, you may trigger a loop. - Keep logic lightweight: Observers should not contain complex operations like heavy computations or I/O.
- Don’t rely on initialization triggers: Observers won’t fire during direct property initialization inside
init()
. - Use observers for side effects, not for value computation: Keep logic deterministic and side-effect focused.
Summary
Swift property observers
provide a robust way to react to changes in stored property values. By using willSet
and didSet
, you can update UI elements, log state changes, validate data, or trigger synchronization across your app. These observers are simple to implement, highly readable, and offer fine-grained control over property behavior.
Knowing when to use property observers Swift
developers often face helps strike the right balance between reactive and clean code. They are a vital tool in many common programming patterns, especially in SwiftUI, where state-driven updates are central to UI behavior.
Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.