How to Use Computed Properties in Swift

What you’ll build or solve

You’ll define computed properties that derive values from stored properties.

When this approach works best

Computed properties work best when:

  • A value can always be derived from other stored properties, like area from width and height.
  • You want to avoid duplicated state that can drift out of sync, like storing both side and area.
  • You want a clean property-style API instead of calling a method, like user.initials instead of user.getInitials().

This is a bad idea when the computation is heavy and runs often. In that case, cache the result or compute it once and store it.

Prerequisites

  • Xcode or a Swift Playground
  • Basic knowledge of Swift structs or classes and stored properties

Step-by-step instructions

Step 1: Create a read-only computed property

A read-only computed property has only a getter. Swift calculates it every time you access it.

structRectangle {
varwidth:Double
varheight:Double

vararea:Double {
width*height
    }
}

What to look for

  • No initial value for area, because Swift does not store it.
  • Changing width or height changes area automatically.

Step 2: Create a read-write computed property with a setter

Add a setter when you want assignments to update other stored properties.

importFoundation

structSquare {
varside:Double

vararea:Double {
get {side*side }
set {side=sqrt(newValue) }
    }
}

What to look for

  • newValue is available automatically inside set.
  • The setter updates a stored property (side), not area itself.

Step 3: Know what to look for with computed properties

Computed properties stay predictable when you follow a few rules.

What to look for

  • Single-expression getters can omit return, which keeps simple computed properties short.
  • Setters should update stored properties, not the computed property itself.
  • Custom setter parameter names exist, but renaming newValue rarely improves clarity unless the meaning is specific.
set(newArea) {
side=sqrt(newArea)
}
  • Computed properties run on every access, so avoid heavy work in getters if the property is read often.

Examples you can copy

Example 1: Derived full name

structUser {
varfirstName:String
varlastName:String

varfullName:String {
"\(firstName) \(lastName)"
    }
}

letuser=User(firstName:"Jordan",lastName:"Lee")
print(user.fullName)

Example 2: Temperature conversion with two-way updates

importFoundation

structTemperature {
varcelsius:Double

varfahrenheit:Double {
get {celsius*9/5+32 }
set {celsius= (newValue-32)*5/9 }
    }
}

vartemp=Temperature(celsius:0)
print(temp.fahrenheit)

temp.fahrenheit=212
print(temp.celsius)

Example 3: Cart total that never goes stale

structCartItem {
varprice:Double
varquantity:Int
}

structCart {
varitems: [CartItem]

vartotal:Double {
items.reduce(0) {$0+ ($1.price*Double($1.quantity)) }
    }
}

letcart=Cart(items: [
CartItem(price:10,quantity:2),
CartItem(price:5,quantity:3)
])

print(cart.total)

Common mistakes and how to fix them

Mistake 1: Storing derived data that can drift out of sync

What you might do:

structRectangle {
varwidth:Double
varheight:Double
vararea:Double
}

Why it breaks: area can become wrong when width or height changes.

Correct approach:

structRectangle {
varwidth:Double
varheight:Double

vararea:Double {
width*height
    }
}

Mistake 2: Creating infinite recursion in a setter

What you might do:

importFoundation

structSquare {
varside:Double

vararea:Double {
get {side*side }
set {area=newValue }
    }
}

Why it breaks: Assigning to area inside its own setter calls the setter again.

Correct approach:

importFoundation

structSquare {
varside:Double

vararea:Double {
get {side*side }
set {side=sqrt(newValue) }
    }
}

Troubleshooting

  • If you see Cannot assign to property: 'x' is a get-only property, add a set block.
  • If you see Cannot use mutating member on immutable value, change your instance from let to var before setting a computed property.
  • If values seem wrong after setting, confirm the setter updates the right stored property.
  • If performance feels slow, move heavy work out of the getter or cache the result.

Quick recap

  • Use a read-only computed property to derive values without storing them.
  • Add a setter when assignments should update stored properties.
  • Use newValue inside setters to read the incoming value.
  • Update stored properties in setters, not the computed property itself.
  • Avoid heavy computations in getters when the property is accessed often.