WWDC24 deal: 30% off our Swift and SwiftUI books! Learn more ...WWDC24 deal:30% off our Swift and SwiftUI books >>

Trigger property observers from initializers in Swift

In Swift, property observers such as willSet and didSet are not called when a property is set in an initializer. This is by design, as the initializer's purpose is to set up the initial state of an object, and during this phase, the object is not yet fully initialized. However, if we need to perform some actions similar to what we'd do in property observers during initialization, there are some workarounds.

# Set properties after initialization

One approach is to set the properties after the object has been initialized.

class MyClass {
    var myProperty: String {
        willSet {
            print("Will set myProperty to \(newValue)")
        }
        didSet {
            print("Did set myProperty to \(myProperty), previously \(oldValue)")
        }
    }

    init() {
        myProperty = "Initial value"
    }
}

let myObject = MyClass()
myObject.myProperty = "New value"

In this example, the property observers will not trigger during the initial assignment in the initializer but will trigger on subsequent property changes.

# Separate property setup method

Another approach is to use a separate method to set up the property.

class MyClass {
    var myProperty: String {
        willSet {
            print("Will set myProperty to \(newValue)")
        }
        didSet {
            print("Did set myProperty to \(myProperty), previously \(oldValue)")
        }
    }
    
    init(value: String) {
        myProperty = "Initial value"
        setupPropertyValue(value: value)
    }
    
    private func setupPropertyValue(value: String) {
        myProperty = value
    }
}

let myObject = MyClass(value: "New value")

This approach ensures that the property observers are triggered during the setup phase after the initialization of the object is completed.

# Create a defer closure

An alternative approach involves using a defer block within the initializer.

class MyClass {
    var myProperty: String {
        willSet {
            print("Will set myProperty to \(newValue)")
        }
        didSet {
            print("Did set myProperty to \(myProperty), previously \(oldValue)")
        }
    }

    init(value: String) {
        defer { myProperty = value } 
        myProperty = "Initial value"
    }
}

let myObject = MyClass(value: "New value")

The defer block ensures that the didSet logic is called after the initial value is set.

# Manually trigger side effects

If we need to perform some specific actions during initialization, we can also manually call the same methods or code blocks that we would have called in our observers.

class MyClass {
    var myProperty: String {
        willSet {
            propertyWillChange(newValue)
        }
        didSet {
            propertyDidChange(oldValue)
        }
    }

    init(value: String) {
        myProperty = value
        propertyDidChange(nil)
    }

    private func propertyWillChange(_ newValue: String) {
        print("Will set myProperty to \(newValue)")
    }

    private func propertyDidChange(_ oldValue: String?) {
        print("Did set myProperty to \(myProperty), previously \(oldValue)")
    }
}

let myObject = MyClass(value: "New value")

In this example, the propertyDidChange() method is manually called within the initializer to simulate the didSet observer.


While property observers don't fire during initialization, these workarounds offer alternative ways to achieve similar behavior. We choose the approach that best fits our use case and coding style.

As someone who has worked extensively with Swift, I've gathered many such insights over the years. I'm excited to share these in my new book Swift Gems. This book is packed with advanced tips and techniques to help intermediate and advanced Swift developers enhance their coding skills. From optimizing collections and handling strings to mastering asynchronous programming and debugging, "Swift Gems" provides practical advice to elevate your Swift development. Grab your copy of Swift Gems and let's explore the advanced techniques together.

Books by Natalia PanferovaBooks by Natalia Panferova
WWDC24: 30% off all books!
  • Swift Gems

    100+ tips to take your Swift code to the next level

  • Integrating SwiftUI into UIKit Apps

    A detailed guide on gradually adopting SwiftUI in UIKit projects

The offer is active until the 16th of June.