Struct vs Class in Swift: When to use which

Md. Ahsanul Haque

27 October, 2025

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?

  1. user1 is created in memory with name = "Ahsan" and age = 25.
  2. When we do var user2 = user1, Swift copies all the data into a new memory slot.
  3. Now user1 and user2 are completely independent.
  4. Changing user2 does not affect user1.

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?

  1. user1 points to a User object in memory.
  2. user2 = user1 only copies the reference (memory address), not the data.
  3. Both user1 and user2 point to the same object.
  4. Changing user2.name also changes user1.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)
Both structs and classes can have initializers (init) to set up their data:
				
					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)
				
			
For classes, you can also use deinitializer (deinit), which runs when the object is destroyed:
				
					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
In one line: Structs = independent photocopies. Classes = shared Google Docs.
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.

Md. Ahsanul Haque

27 October, 2025