ProgrammingiOS Developer

How do property observers work in Swift, and why are they needed?

Pass interviews with Hintsage AI assistant

Answer.

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 changes
  • didSet is called after a new value is assigned

Observers 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:

  • In the willSet observer, a special variable newValue is available
  • In didSet, oldValue is available
  • Observers are not called when initializing the property in init

Trick questions.

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

Common mistakes and anti-patterns

  • Dependency on side effects: implementing business logic only in didSet/willSet makes the code opaque
  • Incorrect management of side effects during "empty" value changes when it hasn't changed
  • Using observers for computed properties instead of implementing behavior in the setter

Real-life example

Negative case

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:

  • Fast implementation, little code

Cons:

  • Increased number of unnecessary operations, debugging became harder

Positive case

In didSet, equality between old and new values was checked. The interface was updated only if the value genuinely changed.

Pros:

  • Minimization of side effects, high performance

Cons:

  • Required an additional if check, slightly more code