Swift

Is it possible to allow didSet to be called during initialization in Swift

25 September 2026 · 5 min read

Is it possible to allow didSet to be called during initialization in Swift

Swift developers often encounter a nuanced behavior regarding property observers, specifically the didSet observer, and its interaction with initialization. The question arises: can didSet be triggered during the initialization process of a Swift class or struct? Understanding this behavior is crucial for predictable and reliable state management within your Swift applications. This article delves into the intricacies of didSet and initialization, exploring the underlying mechanisms and providing practical solutions for managing property changes during object creation.

Understanding Property Observers in Swift

Property observers, namely willSet and didSet, provide a powerful mechanism for responding to changes in a property’s value. didSet, in particular, is executed immediately after a new value is assigned to a property. This allows for side effects like updating the UI, validating input, or triggering other dependent actions. However, the default behavior during initialization requires careful consideration.

By default, property observers are not called during initialization. This is a deliberate design choice to ensure that an object is fully initialized before any side effects from didSet are triggered. Imagine a scenario where didSet attempts to access other properties that haven’t yet been assigned their initial values; this could lead to unexpected behavior or crashes.

Why didSet Doesn’t Fire During Initialization

Swift prioritizes safety and predictability during object initialization. Calling didSet prematurely could lead to inconsistencies and unexpected behavior. Consider a class where didSet on one property relies on the value of another property. If didSet were called before all properties were initialized, it might access uninitialized values, leading to errors.

This behavior also simplifies the initialization process. By delaying didSet execution, Swift guarantees that initialization logic is executed in a predictable order, preventing complex interdependencies between properties and their observers.

For instance, consider a User class with a fullName property that is derived from firstName and lastName:

swift class User { var firstName: String var lastName: String var fullName: String = "" { didSet { print(“Full name changed to: \(fullName)”) } } init(firstName: String, lastName: String) { self.firstName = firstName self.lastName = lastName self.fullName = “\(firstName) \(lastName)” // didSet not called here } } Workarounds for Triggering Actions During Initialization

While the default behavior prevents didSet from firing during initialization, there are scenarios where you might want to perform actions similar to what didSet provides. Here are a few common workarounds:

  1. Post-Initialization Setup: Create a separate method (e.g., setup()) that is called immediately after initialization. This method can perform any necessary setup, including actions you would normally place in didSet.
  2. Computed Properties: If you need to derive a value based on other properties, use a computed property instead. Computed properties are recalculated each time they are accessed, ensuring that they always reflect the current state of the dependent properties.
  3. Custom Setter: For more complex logic, use a custom setter for the property. This allows you to execute code immediately before the new value is assigned. While not exactly equivalent to didSet, it provides similar functionality during initialization.

Best Practices for Property Observers and Initialization

To ensure clean and predictable code, consider these best practices:

  • Keep initialization simple: Focus on assigning initial values to properties and avoid complex logic within the initializer.
  • Use didSet sparingly: Overusing didSet can lead to complex dependencies and make debugging more challenging. Consider alternatives like computed properties or custom setters when appropriate.

For further reading on Swift initialization, consult the official Swift documentation: Initialization - The Swift Programming Language (Swift 5.7).

Place infographic here illustrating the initialization process and the role of property observers.

By understanding the nuances of didSet and initialization, you can write more robust and predictable Swift code. Leveraging alternative approaches like post-initialization setup, computed properties, and custom setters can empower you to manage state changes effectively throughout the lifecycle of your objects. This ultimately leads to cleaner, more maintainable, and bug-free applications. Learn more about property observers in Apple’s official documentation.

For more in-depth knowledge on Swift best practices, check out this style guide. This comprehensive resource provides further insight into writing clean, maintainable Swift code, covering various aspects of the language and its best practices. Exploring these guidelines can significantly improve your Swift development skills. Consider visiting our blog for more practical tips and tricks on Swift development.

FAQ

Q: Can I force didSet to be called during initialization?

A: Not directly. The behavior of didSet is intentionally designed to prevent execution during initialization. However, workarounds like post-initialization setup provide equivalent functionality.

Question & Answer :

Question

Apple’s docs specify that:

willSet and didSet observers are not called when a property is first initialized. They are only called when the property’s value is set outside of an initialization context.

Is it possible to force these to be called during initialization?

Why?

Let’s say I have this class

class SomeClass { var someProperty: AnyObject { didSet { doStuff() } } init(someProperty: AnyObject) { self.someProperty = someProperty doStuff() } func doStuff() { // do stuff now that someProperty is set } } 

I created the method doStuff, to make the processing calls more concise, but I’d rather just process the property within the didSet function. Is there a way to force this to call during initialization?

Update

I decided to just remove the convenience intializer for my class and force you to set the property after initialization. This allows me to know didSet will always be called. I haven’t decided if this is better overall, but it suits my situation well.

If you use defer inside of an initializer, for updating any optional properties or further updating non-optional properties that you’ve already initialized and after you’ve called any super.init() methods, then your willSet, didSet, etc. will be called. I find this to be more convenient than implementing separate methods that you have to keep track of calling in the right places.

For example:

public class MyNewType: NSObject { public var myRequiredField:Int public var myOptionalField:Float? { willSet { if let newValue = newValue { print("I'm going to change to \(newValue)") } } didSet { if let myOptionalField = self.myOptionalField { print("Now I'm \(myOptionalField)") } } } override public init() { self.myRequiredField = 1 super.init() // Non-defered self.myOptionalField = 6.28 // Defered defer { self.myOptionalField = 3.14 } } } 

Will yield:

I'm going to change to 3.14 Now I'm 3.14