willSet and didSet

Swift language Junior Swift 5.0+ iOS 17+ Reviewed By Alok Singh

Predict the output

What does this print?

struct Box {
    var value = 0 {
        willSet { print("will \(newValue)") }
        didSet { print("did \(oldValue)") }
    }
    init() { value = 1 }
}
var b = Box()
b.value = 2
Options
Hint 1 of 1

Do observers fire inside init?

Choose an answer, then open Show answer below to check it.

Show answer

Answer: B will 2, did 1

Correct. Only the assignment after init triggers the observers.

Why not the others?
  • A will 1, did 0, will 2, did 1. Observers don't run when the type's own initializer sets the property.
  • C did 1. willSet runs too, before the change.
  • D Nothing. Assignments outside init do trigger observers.

30-second answer

willSet runs just before a stored property changes (with newValue), and didSet runs just after (with oldValue). They are not called while the type's own initializer sets the property, or when the property is set before the object is fully initialized. They are useful for small side effects like updating a label.

Practise saying it · 30 s. No recording, just a timer

Explain property observers.

Say your answer out loud, then check which of these points you covered:

  • willSet / didSet
  • Not called in own init
  • Keep them small

Deep dive

Observers fire even if the new value equals the old one.

Subclasses can add observers to inherited properties.

Passing a property as inout triggers its observers when the function returns.

In SwiftUI and Observation, prefer computed state over side effects in observers.

Common mistakes

  • Expecting observers to run during init.
  • Doing heavy work or networking in didSet.

Senior take & follow-ups

Seniors know the init exception and keep observers small.

Follow-up questions

Think of your answer first, then open the hint.

  1. Do observers run when set through inout?

    Show hint

    Yes, on write-back.

  2. How do you skip work when the value didn't change?

    Show hint

    Compare oldValue in didSet.

Suggest a fix if something here is wrong or out of date.