Updated for Xcode 14.2
Structs can have two kinds of property: a stored property is a variable or constant that holds a piece of data inside an instance of the struct, and a computed property calculates the value of the property dynamically every time it’s accessed. This means computed properties are a blend of both stored properties and functions: they are accessed like stored properties, but work like functions.
As an example, previously we had an Employee
struct that could track how many days of vacation remained for that employee. Here’s a simplified version:
struct Employee {
let name: String
var vacationRemaining: Int
}
var archer = Employee(name: "Sterling Archer", vacationRemaining: 14)
archer.vacationRemaining -= 5
print(archer.vacationRemaining)
archer.vacationRemaining -= 3
print(archer.vacationRemaining)
That works as a trivial struct, but we’re losing valuable information – we’re assigning this employee 14 days of vacation then subtracting them as days are taken, but in doing so we’ve lost how many days they were originally granted.
We could adjust this to use computed property, like so:
struct Employee {
let name: String
var vacationAllocated = 14
var vacationTaken = 0
var vacationRemaining: Int {
vacationAllocated - vacationTaken
}
}
Now rather than making vacationRemaining
something we can assign to directly, it is instead calculated by subtracting how much vacation they have taken from how much vacation they were allotted.
When we’re reading from vacationRemaining
, it looks like a regular stored property:
var archer = Employee(name: "Sterling Archer", vacationAllocated: 14)
archer.vacationTaken += 4
print(archer.vacationRemaining)
archer.vacationTaken += 4
print(archer.vacationRemaining)
This is really powerful stuff: we’re reading what looks like a property, but behind the scenes Swift is running some code to calculate its value every time.
We can’t write to it, though, because we haven’t told Swift how that should be handled. To fix that, we need to provide both a getter and a setter – fancy names for “code that reads” and “code that writes” respectively.
In this case the getter is simple enough, because it’s just our existing code. But the setter is more interesting – if you set vacationRemaining
for an employee, do you mean that you want their vacationAllocated
value to be increased or decreased, or should vacationAllocated
stay the same and instead we change vacationTaken
?
I’m going to assume the first of those two is correct, in which case here’s how the property would look:
var vacationRemaining: Int {
get {
vacationAllocated - vacationTaken
}
set {
vacationAllocated = vacationTaken + newValue
}
}
Notice how get
and set
mark individual pieces of code to run when reading or writing a value. More importantly, notice newValue
– that’s automatically provided to us by Swift, and stores whatever value the user was trying to assign to the property.
With both a getter and setter in place, we can now modify vacationRemaining
:
var archer = Employee(name: "Sterling Archer", vacationAllocated: 14)
archer.vacationTaken += 4
archer.vacationRemaining = 5
print(archer.vacationAllocated)
SwiftUI uses computed properties extensively – you’ll see them in the very first project you create!
SPONSORED From March 20th to 26th, you can join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer!
Sponsor Hacking with Swift and reach the world's largest Swift community!
Link copied to your pasteboard.