Structs, Classes & Swift's Value/Reference Model
iOS Development Fundamentals
Chapter 4 · Structs, Classes & Swift's Value/Reference Model
This chapter closes out core Swift with its single most consequential design decision: structs are value types, classes are reference types. Getting this distinction genuinely intuitive now is what makes SwiftUI's own view code — starting next chapter — make sense as a coherent design, not a set of memorized rules.
Struct and Class Syntax Side by Side
The syntax looks almost identical — properties, methods, both support initializers. The real difference is invisible in the declaration itself, and only shows up the moment a value is assigned or passed around.
The Core Distinction: Copy vs. Share
Assigning or passing it creates a real, independent copy. No shared state, no surprises from one place changing another's data.
Assigning or passing it shares the same underlying instance. Changing it through one reference is visible through every other reference to it.
String, Array,
Dictionary — are all real structs, not classes. Apple's own real, deliberate design choice for
the language leans toward value types by default; classes are reached for specifically when shared,
mutable identity is genuinely needed.
Mutating Methods
Because a struct instance's own properties can't change from inside a regular method (structs are
immutable by default from within their own methods), a method that needs to modify self must
be explicitly marked mutating:
mutating method can only be called on a struct stored in a var, never a
let — the compiler enforces this directly, since a let constant's own value is
never allowed to change, and a mutating method genuinely replaces the whole instance's own value under the
hood.
Identity vs. Equality
For classes, Swift distinguishes two real, different questions: are two references pointing at the exact
same underlying instance (===), or do two instances just happen to hold equal values
(==, which a type has to explicitly opt into via Equatable)?
Structs, being value types with no shared identity to begin with, only ever use == — and
Swift can generate that conformance to Equatable automatically for a struct whose own
properties are all themselves Equatable.
A First, Brief Look at ARC
Every class instance is managed by Automatic Reference Counting (ARC) — Swift keeps a
real count of how many references currently point at a given instance, and deallocates it automatically
once that count reaches zero. This is what makes the shared, reference-type behavior above safe to use
without manual memory management. It's also, per Chapter 3's own closing note, the real source of strong
reference cycles — two class instances each holding a strong reference to the other, which ARC can't
resolve on its own. This course's own second course, Architecture & Data, covers weak and
unowned references — the real fix — once classes are used more heavily for real app state.
View types (introduced in
Chapter 1, covered fully from Chapter 5) are structs specifically because a view needs to be cheap to
create and recreate — SwiftUI rebuilds view structs constantly as state changes, and copying a lightweight
struct with no ARC bookkeeping involved is genuinely far cheaper than allocating and reference-counting a
class instance every time.
Hands-On Exercises
Define a struct Rectangle with var width: Double and var height: Double, and a mutating method scale(by factor: Double) that multiplies both. Create one instance, copy it to a second variable, scale only the copy, and print both instances' widths to confirm the original is unaffected.
Define a class ShoppingCart with var itemCount = 0 and a method addItem() that increments it. Create one instance, assign it to a second constant, call addItem() on the second, and print both constants' itemCount to confirm they show the same real, shared value.
Explain, in your own words, why SwiftUI deliberately builds its own View types as structs rather than classes, connecting your answer to both the copy-vs-share distinction and ARC.
Chapter 4 Quick Reference
struct= value type — assigning/passing copies it;class= reference type — assigning/passing shares the same instanceString,Array, andDictionaryare all real structs in Swift's own standard library- A struct method that modifies
selfmust be markedmutating, and can only be called on avar ===checks reference identity (classes only);==checks value equality (viaEquatable)- Classes are managed by ARC, which is also the real source of strong reference cycles — covered with the real fix in Architecture & Data
- SwiftUI's own
Viewtypes are structs specifically because they need to be cheap to create and recreate constantly