Stored Properties / Computed Properties / lazy
Swift properties come in three kinds: stored properties that hold a value directly, computed properties that calculate a value on access, and lazy properties that are initialized only on first access.
Syntax
struct / class TypeName {
// Stored property
var variableName: Type = initialValue
let constantName: Type
// Computed property (get + set)
var computed: Type {
get { return value }
set { storedProperty = newValue }
}
// Computed property (get only)
var readOnly: Type { return value }
// Lazy property (initialized on first access)
lazy var name: Type = initializationExpression
// Property observer
var monitored: Type {
willSet { print("Before change: \(newValue)") }
didSet { print("After change: \(oldValue) → \(monitored)") }
}
// Type property
static var shared: Type = initialValue
}
Syntax overview
| Syntax | Description |
|---|---|
| var / let property | A property that stores a value directly. |
| var computed: T { get set } | A read-write property that calculates and returns a value. |
| var readOnly: T { return ... } | A read-only property that calculates and returns a value. |
| lazy var | A property that is initialized only the first time it is accessed. |
| willSet / didSet | Observers called before and after a property value changes. |
| static var / let | A property that belongs to the type itself, not to an instance. |
Sample code
class Temperature {
// Stored property (Celsius)
var celsius: Double {
willSet { print("Before change: \(celsius)°C") }
didSet { print("After change: \(celsius)°C") }
}
// Computed property (Celsius ↔ Fahrenheit conversion)
var fahrenheit: Double {
get { return celsius * 9 / 5 + 32 }
set { celsius = (newValue - 32) * 5 / 9 }
}
// Read-only
var kelvin: Double {
return celsius + 273.15
}
// Lazy property (calculated on first access)
lazy var boilingPoint: String = {
print("Calculating boiling point...")
return "100°C"
}()
// Type property
static let absoluteZero = -273.15
init(_ celsius: Double) {
self.celsius = celsius
}
}
let temp = Temperature(20.0)
print("Celsius: \(temp.celsius)°C")
print("Fahrenheit: \(temp.fahrenheit)°F")
print("Kelvin: \(temp.kelvin)K")
// Verify willSet / didSet behavior
temp.celsius = 100.0
print("100°C = \(temp.fahrenheit)°F")
// Lazy: initialized only on first access
print(temp.boilingPoint)
print(temp.boilingPoint) // Second access does not print "Calculating..."
// Type property
print("Absolute zero: \(Temperature.absoluteZero)°C")
Notes
Computed properties do not store a value — they calculate and return one each time they are accessed. Omitting the setter (set) makes the property read-only. Inside a setter, you can use the implicit argument name newValue.
The lazy keyword is well-suited for objects that are expensive to initialize. The value is not created when the instance is initialized; it is created only the first time the property is accessed. A lazy property must be declared with var, not let. Also, accessing a lazy property on a struct requires a var instance.
For the differences between struct and class, see struct basics / memberwise initializer.
If you find any errors or copyright issues, please contact us.