When you start learning Swift, you will often hear this:
“Structs are value types, and classes are reference types.”
If you’re new to programming, this might sound confusing. But don’t worry; by the end of this article, you’ll understand exactly what this means, how Swift handles memory, and when to use structs versus classes.
Let’s break it down step by step with examples, stories, and diagrams.
Meet Structs: The Copy Machine
Think of a struct as a blueprint for creating independent copies of data. Every time you assign a struct to a new variable or pass it to a function, Swift makes a copy of that struct.
Here’s a simple example:
struct User {
var name: String
var age: Int
}
var user1 = User(name: "Ahsan", age: 25)
var user2 = user1 // Makes a COPY
user2.name = "Shantanur"
print(user1.name) // Ahsan
print(user2.name) // Shantanur
What’s happening here?
user1is created in memory withname = "Ahsan"andage = 25.- When we do
var user2 = user1, Swift copies all the data into a new memory slot. - Now user1 and user2 are completely independent.
- Changing
user2does not affectuser1.
Analogy:
Imagine you have a photocopy of a document. Each copy is independent; you can write on your copy without affecting mine. That’s exactly how structs behave.
Meet Classes: The Shared Notebook
A class works differently. When you assign a class to a new variable, Swift does not copy the data. Instead, both variables point to the same memory location.
class User {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
var user1 = User(name: "Ahsan", age: 25)
var user2 = user1 //Shares the same object
user2.name = "Shantanur"
print(user1.name) // Shantanur
What’s happening here?
user1points to a User object in memory.user2 = user1only copies the reference (memory address), not the data.- Both
user1anduser2point to the same object. - Changing
user2.namealso changesuser1.name.
Analogy:
Think of a Google Doc shared between two people. Both of you can edit the same document. If one person makes a change, the other sees it immediately. That’s how classes behave; they are reference types.
Value Type vs Reference Type: Memory View
Let’s visualize how Swift stores structs and classes:
Struct (Value Type)
var a = User(name: "Ahsan", age: 25)
var b = a
b.name = "Shantanur"
Memory View (Stack Only):
STACK MEMORY
──────────────────────────────
| a | {name: "Ahsan"} |
| b | {name: "Shantanur"} |
──────────────────────────────
Each variable owns its own data.
Structs are stored in stack memory, which is fast and automatically cleaned up when out of scope.
Class (Reference Type)
var a = User(name: "Ahsan", age: 25)
var b = a
b.name = "Shantanur"
Memory View (Stack + Heap):
STACK MEMORY HEAP MEMORY
────────────────────── ─────────────────────────
| a | ───────────────▶ | Object 0x1001 |
| b | ───────────────┘ | name: "Shantanur" |
────────────────────── ─────────────────────────
Both a and b point to the same object on the heap.
Changing one affects the other.
Initializers (init) and Deinitializers (deinit)
struct Point {
var x: Int
var y: Int
init(x: Int, y: Int) {
self.x = x
self.y = y
}
}
let p = Point(x: 5, y: 10)
class Person {
var name: String
init(name: String) { self.name = name }
deinit { print("\(name) is gone!") }
}
Structs do not have deinit because Swift automatically manages memory for value types.
When to Use Structs
Swift recommends using structs by default. Use structs when:
- You have simple, independent data (coordinates, colors, user info).
- Each copy should be separate and safe.
- You don’t need inheritance.
Examples:String, Array, Dictionary; all are structs in Swift. Swift uses copy-on-write optimization, so large arrays are not copied unnecessarily.
When to Use Classes
Use classes when:
- You need a shared, mutable state.
- You want inheritance or polymorphism.
- You need deinitialization for cleanup.
Examples:UIView, UIViewController, NSFileManager; all are classes.
Quick Summary Table
| Feature | Struct | Class |
| Type | Value | Reference |
| Memory | Stack | Heap |
| Copy Behavior | Creates independent copy | Shares same reference |
| Mutation | Safe (affects only that copy) | Affects all references |
| Inheritance | No | Yes |
| Cleanup (deinit) | No | Yes |
| Best for | Simple, independent data | Shared or complex objects |
Final Thoughts
- Structs are safe, predictable, and fast.
- Classes are powerful for shared data and inheritance.
- Understanding this difference is key to writing clean Swift code.
When in doubt, start with structs. Only use classes when you truly need shared state or object-oriented features.







