Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A stored property is a constant or variable bound directly to an instance of a structure or class, or to a type itself. It allocates memory to hold a specific value as part of the overall memory layout. Unlike computed properties, which calculate their values dynamically, stored properties persist their data in memory until the instance or type is deallocated. Stored properties are declared using the var keyword for mutable variables or the let keyword for immutable constants. While structures and classes can define both stored instance properties and stored type properties, enumerations in Swift can only define stored type properties (using the static keyword) and cannot contain stored instance properties.
struct NetworkResponse {
    var statusCode: Int      // Variable stored instance property (mutable)
    let payload: String      // Constant stored instance property (immutable)
    static var retries = 3   // Variable stored type property
}

Initialization Requirements

Swift enforces strict initialization safety. Every stored instance property must be assigned a valid value by the time the instance’s initialization phase completes. This can be achieved either by providing a default value at the point of declaration or by assigning a value within an initializer (init).
class Session {
    // Initialized via default value
    var timeoutInterval: Double = 60.0 
    
    // Uninitialized at declaration; requires initialization in init()
    let sessionID: String 

    init(sessionID: String) {
        self.sessionID = sessionID
    }
}

Lazy Stored Properties

A lazy stored property delays the calculation and memory allocation of its initial value until the exact moment it is first accessed. This is declared using the lazy modifier. Lazy properties must always be declared as variables (var). They cannot be constants (let) because constant properties must possess a value before initialization completes, whereas lazy properties are evaluated post-initialization.
class DataProcessor {
    // The closure is only executed if and when 'heavyResource' is accessed
    lazy var heavyResource: [String: Any] = {
        var resource = [String: Any]()
        // Expensive allocation or computation logic here
        return resource
    }()
}

Property Observers

Stored properties can implement property observers to monitor and respond to changes in their value. Observers are triggered every time the property’s value is set, even if the new value is identical to the current value. Crucially, property observers are not called during the initial assignment of a property. This means observers do not trigger when a default value is applied at declaration, nor do they trigger when a property is assigned a value inside an init method. They are only invoked on subsequent assignments.
  • willSet: Called immediately before the value is stored. Provides a default newValue parameter.
  • didSet: Called immediately after the new value is stored. Provides a default oldValue parameter.
Note: Property observers cannot be applied to lazy stored properties.
class StateMachine {
    var state: Int = 0 {
        willSet {
            print("State will change to \(newValue)")
        }
        didSet {
            print("State changed from \(oldValue)")
        }
    }
    
    init(initialState: Int) {
        // This assignment does NOT trigger willSet or didSet
        self.state = initialState 
    }
}

Mutability Semantics

The mutability of a stored property depends on both its declaration (var vs. let) and the nature of the type it belongs to (value type vs. reference type). If an instance of a value type (a struct) is assigned to a constant (let), all of its stored properties become immutable, even if they were declared as var. This occurs because value types exhibit deep immutability when assigned to a constant.
struct Point {
    var x: Int
    var y: Int
}

let origin = Point(x: 0, y: 0)
// origin.x = 10 // Compiler Error: 'origin' is a 'let' constant
Conversely, if an instance of a reference type (a class) is assigned to a constant, its variable stored properties can still be mutated. The constant only protects the reference to the instance, not the underlying data within the instance.
Master Swift with Deep Grasping Methodology!Learn More