Swift Properties
A property is a named value that belongs to a struct, class, or enum. Properties describe what an object knows about itself. A student has a name, a car has a color, and a bank account has a balance. Swift offers several kinds of properties, and each kind solves a different problem.
Consider a house. The furniture inside is stored data. The total floor area comes from a calculation using length and width. A doorbell reacts whenever someone arrives. Swift maps these three ideas to stored properties, computed properties, and property observers.
Diagram: Kinds of Properties
Properties
|
+----------------+------------------+
| | |
Stored Computed Type
(keeps a value) (calculates one) (belongs to the type)
|
+--+-----------+
| |
lazy observers
(built (willSet,
on demand) didSet)Stored Properties
A stored property keeps a value in memory. Declare it with let for a fixed value or var for a changeable value.
struct Book {
let title: String
var pagesRead: Int = 0
}
var novel = Book(title: "Sky Road")
novel.pagesRead = 120
print("\(novel.title): \(novel.pagesRead) pages")
// Output: Sky Road: 120 pagesComputed Properties
A computed property stores nothing. It runs a small calculation every time you read it. A computed property accepts a new value through a setter.
struct Rectangle {
var width: Double
var height: Double
var area: Double {
width * height
}
}
let room = Rectangle(width: 4, height: 5)
print(room.area) // Output: 20.0The area property always matches the current width and height. No stale data can appear.
Getters and Setters
struct Temperature {
var celsius: Double
var fahrenheit: Double {
get {
celsius * 9 / 5 + 32
}
set {
celsius = (newValue - 32) * 5 / 9
}
}
}
var today = Temperature(celsius: 100)
print(today.fahrenheit) // Output: 212.0
today.fahrenheit = 32
print(today.celsius) // Output: 0.0The setter receives the incoming value under the automatic name newValue. Both properties stay in sync because only celsius holds real data.
Property Observers
Observers watch a stored property and run code when its value changes. The willSet block runs before the change, and the didSet block runs after it.
class StepTracker {
var steps = 0 {
willSet {
print("About to set steps to \(newValue)")
}
didSet {
print("Added \(steps - oldValue) steps")
}
}
}
let tracker = StepTracker()
tracker.steps = 500
// Output:
// About to set steps to 500
// Added 500 stepsObservers suit tasks such as refreshing a screen label or saving a score after every change.
Lazy Properties
A lazy property delays its creation until code reads it for the initial time. Heavy work that might never be needed benefits from this trick.
class Report {
lazy var summary: String = {
print("Building summary...")
return "Sales grew by 8 percent"
}()
}
let report = Report()
print("Report created")
print(report.summary)
// Output:
// Report created
// Building summary...
// Sales grew by 8 percentMark a lazy property with var, because its value arrives after the object exists.
Type Properties
A type property belongs to the type itself and not to one instance. Every instance shares it. Declare it with the static keyword.
struct Circle {
static let pi = 3.14159
var radius: Double
var area: Double {
Circle.pi * radius * radius
}
}
print(Circle.pi) // Output: 3.14159
print(Circle(radius: 2).area) // Output: 12.56636Choosing the Right Kind
Pick a stored property for data that needs a place in memory. Pick a computed property for a value derived from other properties. A computed property never goes out of date, and a stored copy of the same value can.
Property observers fit side effects such as updating a label or saving a score. Avoid heavy work inside didSet, because the code runs on every change.
Common Mistakes
Reading the property inside its own getter creates an endless loop. A computed property must read other properties only.
Observers do not run during initialization of the same type. Assign the value after the instance exists when you need the observer to fire.
Real-World Use
Fitness apps store steps and compute the daily goal percentage. Weather apps store Celsius and compute Fahrenheit. Forms use observers to enable a submit button the moment every field holds valid text.
Properties in Enums and Classes
Structs, classes, and enums all support computed properties and type properties. Enums cannot hold stored instance properties, but each case can carry associated values and expose computed properties that describe the case. Classes support every kind of property, and observers on a class property fire when a subclass changes the value.
Constants declared with let inside a struct lock the value after initialization. A constant struct instance locks every property, including those declared with var. A constant class instance locks only the reference. The properties inside remain changeable.
Key Takeaways
- Stored properties keep values, and computed properties calculate them.
- Observers react to changes with
willSetanddidSet. - Lazy properties build their value on first use.
- Type properties belong to the type and use the
statickeyword.
