DEV Community

Gamya
Gamya

Posted on

Swift Structs โ€” Computed Properties ๐Ÿ”ฎ

In the last article we built our first structs with stored properties โ€” values that sit in memory and hold data directly. But Swift gives us a second, more dynamic option: computed properties โ€” values that are calculated every time they're accessed, rather than stored. ๐Ÿฅ

Think of it like this: a stored property is like a lunchbox that holds your food. A computed property is like a vending machine โ€” every time you press the button, it calculates and delivers the result fresh.


The Problem With Stored Properties Alone

Let's say we're tracking a ninja's chakra usage:

struct Ninja {
    let name: String
    var chakraRemaining: Int
}

var naruto = Ninja(name: "Naruto", chakraRemaining: 1000)
naruto.chakraRemaining -= 300
print(naruto.chakraRemaining) // 700
naruto.chakraRemaining -= 200
print(naruto.chakraRemaining) // 500
Enter fullscreen mode Exit fullscreen mode

This works, but we're losing important information โ€” we started with 1000 chakra, but once we start subtracting, we've lost track of the original amount. If someone asks "how much chakra has Naruto used?", we can't answer.


Enter Computed Properties

Instead of storing chakraRemaining directly, we can store the original amount and used amount separately, then compute what's remaining:

struct Ninja {
    let name: String
    var chakraTotal = 1000
    var chakraUsed = 0

    var chakraRemaining: Int {
        chakraTotal - chakraUsed
    }
}
Enter fullscreen mode Exit fullscreen mode

Now chakraRemaining is a computed property โ€” it looks like a regular property when you read it, but behind the scenes Swift is running code to calculate the value every time:

var naruto = Ninja(name: "Naruto", chakraTotal: 1000)
naruto.chakraUsed += 300
print(naruto.chakraRemaining) // 700 โ€” calculated automatically!
naruto.chakraUsed += 200
print(naruto.chakraRemaining) // 500 โ€” always up to date!
Enter fullscreen mode Exit fullscreen mode

Notice: we never manually update chakraRemaining. It's always calculated fresh from chakraTotal and chakraUsed, so it's always accurate. ๐ŸŽ‰


Getters and Setters

Right now our computed property is read-only โ€” we can read chakraRemaining, but we can't write to it directly. If you tried:

naruto.chakraRemaining = 400 // โŒ won't compile
Enter fullscreen mode Exit fullscreen mode

Swift would complain because it doesn't know how to handle that assignment. Should it change chakraTotal? Should it change chakraUsed? We haven't told it.

To make a computed property writable, we need to add both a getter (code that reads) and a setter (code that writes):

struct Ninja {
    let name: String
    var chakraTotal = 1000
    var chakraUsed = 0

    var chakraRemaining: Int {
        get {
            chakraTotal - chakraUsed
        }

        set {
            chakraTotal = chakraUsed + newValue
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

A few things to notice:

  • get { } โ€” the code that runs when you read chakraRemaining
  • set { } โ€” the code that runs when you write to chakraRemaining
  • newValue โ€” automatically provided by Swift inside set, representing whatever value was assigned

So if someone sets naruto.chakraRemaining = 400, Swift runs the setter with newValue = 400, and updates chakraTotal accordingly.

Here it is in action:

var naruto = Ninja(name: "Naruto", chakraTotal: 1000)
naruto.chakraUsed += 300
print(naruto.chakraRemaining) // 700

naruto.chakraRemaining = 400  // using the setter
print(naruto.chakraTotal)     // 700 โ€” updated automatically!
Enter fullscreen mode Exit fullscreen mode

Stored vs Computed โ€” Which Should You Use?

Now that you know both types exist, when do you reach for each one?

Use a stored property when:

  • The value doesn't depend on other properties
  • The property is read frequently and the value rarely changes
  • You want to store information that comes from outside (user input, API data, etc.)
struct Hero {
    let name: String       // stored โ€” doesn't change
    var level: Int         // stored โ€” set once, updated occasionally
}
Enter fullscreen mode Exit fullscreen mode

Use a computed property when:

  • The value depends on other properties and should always stay in sync
  • The property is read rarely, so calculating it on demand is fine
  • You want the value to automatically reflect the current state
struct Hero {
    var baseAttack: Int
    var bonusAttack: Int

    var totalAttack: Int {  // computed โ€” always baseAttack + bonusAttack
        baseAttack + bonusAttack
    }
}
Enter fullscreen mode Exit fullscreen mode

The key insight: computed properties are great for derived values โ€” things that can be calculated from data you already have. Instead of manually keeping two values in sync, you store the source data and let the computed property do the math automatically.


A Quick Note on Performance

Computed properties are recalculated every time you access them. For simple calculations like chakraTotal - chakraUsed, that's completely fine โ€” it's almost instant.

But if your computed property did something expensive (like sorting a massive array), calling it thousands of times could slow things down. In those cases, a stored property (updated when needed) would be the smarter choice.

For everything you'll build early on, computed properties are perfectly efficient โ€” just good to keep in the back of your mind as projects grow. ๐ŸŒธ


Why This Matters for SwiftUI

Computed properties are absolutely everywhere in SwiftUI. In fact, the very first thing you'll write in any SwiftUI project is this:

struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
    }
}
Enter fullscreen mode Exit fullscreen mode

That body property? It's a computed property. Every time SwiftUI needs to know what to display, it calls the body getter and gets back a fresh view. You're already using computed properties before you even know it! ๐ŸŽ‰


Wrap Up

Concept What It Means
Stored property A value held in memory, assigned directly
Computed property A value calculated on the fly using code
get The code that runs when you read a computed property
set The code that runs when you write to a computed property
newValue The value being assigned, automatically available inside set

This article was written by me; AI was used to improve grammar and readability.


Top comments (0)