Swift path · Values and types · Topic 1 of 13

Value and reference types

Not started

Swift has two kinds of types. **Value types** (struct, enum, tuples, and almost the whole standard library: Int, String, Array, Dictionary) are copied when assigned or passed. **Reference types** (class, actor, closures) are shared: assignment copies a pointer to one object, managed by reference counting. Swift's style leans heavily on values, because a value can't be changed behind your back.

Why it matters: Whether a type is a struct or a class decides what assignment means. Most surprising Swift bugs (a change that didn't stick, or one that showed up somewhere else) come from mixing the two up.

  1. 1Structs and enums are values

    Assigning or passing a value gives the receiver its own copy; changing one copy never changes another.

  2. 2Classes are references

    Assigning a class instance copies the reference: both names point at the same object, which is counted by ARC.

  3. 3Copy-on-write makes copies cheap

    Array, Dictionary, Set and String share storage until one copy is changed, so copying is O(1) until a write.

  4. 4let means different things

    A let struct can't change at all; a let class reference can't be reassigned, but the object's var properties can.

1

How it works

The explanation, with examples you can run.

The difference in four lines

struct PointValue { var x = 0 }final class PointObject { var x = 0 } var v1 = PointValue(); var v2 = v1; v2.x = 5let o1 = PointObject(); let o2 = o1; o2.x = 5 print(v1.x, v2.x)   // 0 5: two independent valuesprint(o1.x, o2.x)   // 5 5: one shared objectprint(o1 === o2)    // true: identity exists only for references

Note let o1 and o2.x = 5: let on a class reference only fixes which object it points at. On a struct, let freezes every stored property, and methods that change a struct must be marked mutating.

Copy-on-write

Copying a 10,000-element array on every assignment would be slow, so the standard library collections and String use copy-on-write: the value holds a reference to a heap buffer, a copy shares that buffer, and the first mutation of a shared buffer makes a private copy.

var a = Array(repeating: 0, count: 10_000)var b = a            // O(1): same buffer, reference count is now 2b[0] = 1             // the buffer is shared, so b copies it first, then writesprint(a[0], b[0])    // 0 1

Your own structs don't get this automatically. A struct holding a class instance copies the reference, so two struct copies share one object. To give such a type value semantics, implement copy-on-write yourself: keep the class private, and before each mutation check isKnownUniquelyReferenced(&storage), copying the storage if it returns false.

Choosing

  • Use a struct by default: models, configuration, view state, anything that is data. Equality means "same contents", which you get for free with Equatable.
  • Use a class when identity matters (one shared cache, a connection, a view controller), when you need inheritance or deinit, or when interoperating with Objective-C APIs that expect objects.
  • Use an actor when a reference type has mutable state that several tasks will touch (see the concurrency topic).

Costs to know

Values are not automatically on the stack: a struct inside an array, an existential, or a closure capture lives on the heap. Large structs are copied in pieces, and every String, Array or class inside one adds reference-counting traffic. In return the compiler can often skip copies (passing a value as a parameter is a borrow, not a copy) and has no shared mutable state to worry about, which is also what makes value types easy to send between threads in Swift 6.

2

Check yourself

3 questions. Get them all right to finish this topic.

  1. 1.struct Point { var x = 0 }. var a = Point(); var b = a; b.x = 5. What is a.x?
  2. 2.var a = [1, 2, 3]; var b = a. When is the array's storage actually copied?
  3. 3.A struct has a property of a class type. What does copying the struct do to that object?

0 of 3 right so far. Get all three to finish this topic.