Swift
programming
willSet
didSet
property observers

What is the purpose of willSet and didSet in Swift?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

In Swift, properties play a crucial role in defining the characteristics of a class, struct, or enum. While stored and computed properties are widely used, Swift also offers a robust property observer feature through willSet and didSet. These property observers are designed to execute some custom logic in response to property value mutations. This article unpacks the purpose and mechanics of willSet and didSet, including practical examples and key points to consider.

Property Observers Overview

Property observers are employed to monitor changes to a property's value. They are particularly useful when you need to execute specific actions before or after a property is modified. It is important to note that property observers are not available on lazy properties or computed properties with either only a getter or both a getter and setter.

Setting the Scene

Let's start with the fundamental setup to understand how willSet and didSet are integrated into properties:

swift
1class Temperature {
2    var celsius: Double = 0.0 {
3        willSet(newTemperature) {
4            print("Temperature is about to change to \(newTemperature)")
5        }
6        didSet {
7            if celsius > 100 {
8                print("Warning: Temperature has exceeded 100 degrees Celsius!")
9            }
10            print("Old value was: \(oldValue)")
11        }
12    }
13}

In this snippet, celsius is a stored property of the Temperature class. We add two observers:

  • willSet: Triggered just before the value is set. It provides a parameter for the new value, defaulting to newValue if no parameter name is declared.
  • didSet: Invoked immediately after the new value is set. It provides access to the previous value through a default oldValue parameter.

The Purpose of willSet

The primary purpose of willSet is to intercept changes before they actually occur. This allows a developer to prepare for the change, validate conditions, or log the upcoming change for debugging reasons.

Use Cases for willSet:

  • Validation: Ensure the new value conforms to specific rules.
  • Logging: Track changes for auditing purposes.
  • Pre-computation: Trigger computations that need to be ready when the value changes.

Example usage:

swift
1class Wallet {
2    var balance: Double = 0.0 {
3        willSet {
4            if newValue < 0 {
5                print("Warning: Balance is about to be negative.")
6            }
7        }
8    }
9}
10
11let myWallet = Wallet()
12myWallet.balance = -50.0  // Outputs: "Warning: Balance is about to be negative."

The Purpose of didSet

Conversely, didSet serves as an opportunity to react after a property has been updated. Unlike willSet, which provides the impending new value, didSet gives access to the old value, facilitating a comparison with the new one.

Use Cases for didSet:

  • Comparison & Alerts: Alert users if the change is significant.
  • Side Effects: Refresh UI components or trigger events to maintain state consistency.
  • Additional Calculations: Perform calculations that depend on both old and new values.

Example usage:

swift
1class Stock {
2    var shares: Int = 0 {
3        didSet {
4            if shares > oldValue {
5                print("Shares increased by \(shares - oldValue)")
6            }
7        }
8    }
9}
10
11let stock = Stock()
12stock.shares = 200  // Outputs: "Shares increased by 200"
13stock.shares = 250  // Outputs: "Shares increased by 50"

Summary Table

To encapsulate the main points and differences between willSet and didSet, here's a comparison table:

AttributewillSetdidSet
PurposeExecutes before a new value is setExecutes after a new value is set
ParameternewValue (or custom name)oldValue
Use CaseValidation, Logging, Pre-computationAlerts, Side Effects, Calculations
Access Old ValueNoYes
Access New ValueYesNo (but can access property)

Additional Considerations

  • KVO Compliance: Swift's property observers are not tied to Key-Value Observing (KVO), a common API in Objective-C. If you need to support KVO, consider explicitly indicating compliance.
  • Thread Safety: Property observers run on the thread of the modification. If the property is shared across threads, ensure thread safety to avoid anomalies.
  • Complexity: While powerful, avoid overusing willSet and didSet if simple closures or dedicated methods provide more clarity and separation of concerns.

Conclusion

Swift's property observers, willSet and didSet, provide a hands-on way to react before or after a property's value changes. With the flexibility to implement validation, execute computations, or refresh state seamlessly, they are indispensable tools for any seasoned Swift developer. By strategically employing these observers, developers can enhance code maintainability, debuggability, and functionality, ensuring a more responsive application experience.


Course illustration
Course illustration

All Rights Reserved.