Structs and value semanticsswift-6.4/ios-26
Lesson 1 / 7
Unit 1 · The Swift value model

Structs and value semantics

Coming from
Note

Unit 1 · The Swift value model. This is the foundation everything else stands on — especially Unit 2's concurrency, where value semantics is what makes code safe to send.

Swift's default building block for data is the struct, and structs have value semantics: every time you assign one to a variable or pass it to a function, you get an independent copy. Change the copy and the original is untouched. That single rule removes a whole category of bugs before you write a line of concurrency.

Declaring a struct

struct Temperature {
    var celsius: Double

    // A computed property — derived, not stored.
    var fahrenheit: Double {
        celsius * 9 / 5 + 32
    }
}

let boiling = Temperature(celsius: 100)
print(boiling.fahrenheit) // 212.0

celsius is stored; fahrenheit is computed — it holds no memory of its own and recalculates on every read. Swift also synthesizes a memberwise initializer (Temperature(celsius:)) for free, so you rarely write init by hand for a struct.

What "value semantics" actually means

var a = Temperature(celsius: 20)
var b = a          // b is a COPY
b.celsius = 30

print(a.celsius)   // 20  — a never changed
print(b.celsius)   // 30

b = a copies the value. a and b are now two unrelated temperatures. This is the opposite of how objects behave in most languages, where b = a would make both names point at the same object.

Coming from Kotlin

In Kotlin, val b = a for a regular class copies the referencea and b point at the same instance, so mutating one mutates both. Kotlin's data class gives you copy(), but you have to call it. In Swift the copy is the default and automatic; sharing is the thing you have to ask for (a class).

Tip

The Swift default. When you're modeling data — a user, a message, a settings bundle — start with a struct. Reach for a class only when you specifically need shared, mutable identity (one object many things observe) or Apple frameworks require it. "Struct by default" is the single most important habit in modern Swift.

Why this matters later

Value semantics is not just tidy — it's the property that makes a type safe to hand across a concurrency boundary. A value nobody else can secretly mutate can't be part of a data race. When you meet Sendable in Unit 2, remember: structs made of Sendable parts are Sendable for free, precisely because of the copy rule you just learned.

Your turn

Implement value-preserving arithmetic on a Wallet struct.

Value semantics with a struct
Edit the code on the right, then run the hidden tests.

Knowledge check

Q: After var y = x; y.balance = 0, what is x.balance if x is a struct? Unchanged. y is a copy; writing to it can't touch x.

Q: When would you not use a struct? When you need reference semantics on purpose — a single shared instance many parts of the app observe and mutate (e.g. a live network connection, or an @Observable view model in Unit 8). That's a deliberate choice, not the default.

Solution.swiftSwift Testing
ConsoleReady · runs in a sandboxed Swift container
Press Run to compile against the hidden test suite.