How to Use Struct vs Class in Swift

What you’ll build or solve

You’ll learn how structs and classes differ and how that impacts copying, mutation, and shared state.

When this approach works best

Understanding struct vs class works best when:

  • You design data models for an app.
  • You notice unexpected copying or shared mutations.
  • You build SwiftUI views or UIKit controllers.
  • You structure business logic and services.

This comparison is less useful for very small scripts where object design is not important.

Prerequisites

  • Xcode installed
  • Basic Swift syntax
  • Familiarity with variables and functions

Step-by-step instructions

Step 1: Understand value vs reference behavior

Structs are value types. Classes are reference types.

Struct example

struct User {
    var name: String
}

var user1 = User(name: "Alex")
var user2 = user1

user2.name = "Sam"

print(user1.name) // Alex
print(user2.name) // Sam

user2 is a copy. Changing it does not affect user1.

Class example

class User {
    var name: String

    init(name: String) {
        self.name = name
    }
}

var user1 = User(name: "Alex")
var user2 = user1

user2.name = "Sam"

print(user1.name) // Sam
print(user2.name) // Sam

Both variables point to the same instance.

What to look for

  • Structs create independent copies.
  • Classes share the same instance.
  • Shared mutation only happens with classes.

This difference is the most important deciding factor.


Step 2: Choose struct for simple data models

Use a struct when:

  • You store plain data.
  • You want safer, predictable copying.
  • You work with SwiftUI state.
  • You do not need inheritance.

Example:

struct Product {
    var title: String
    var price: Double
}

Structs are ideal for lightweight models. They reduce accidental shared state and make code easier to reason about.


Step 3: Choose class for shared or complex behavior

Use a class when:

  • Multiple parts of your app must share the same instance.
  • You need inheritance.
  • You manage lifecycle or identity.
  • You work with UIKit view controllers.

Example:

class SessionManager {
    var isLoggedIn = false
}

If two objects reference the same SessionManager, changes affect both.

Classes are useful for services and controllers.


Step 4: Understand inheritance differences

Structs do not support inheritance. Classes do.

class Animal {
    func speak() {
        print("Animal sound")
    }
}

class Dog: Animal {
    override func speak() {
        print("Bark")
    }
}

You cannot subclass a struct.

If your design requires polymorphism or shared base behavior, use a class.


Step 5: Consider mutability and intent

Struct methods that modify properties require mutating.

struct Counter {
    var value: Int

    mutating func increment() {
        value += 1
    }
}

Classes do not require mutating.

This encourages immutability with structs, which reduces side effects.

If your type represents a value, like a coordinate or settings object, a struct usually fits better.


Examples you can copy

Example 1: Settings as a struct

struct Settings {
    var isDarkMode: Bool
    var fontSize: Int
}

var settings = Settings(isDarkMode: true, fontSize: 16)
settings.fontSize = 18

Each copy of Settings is independent.


Example 2: Shared manager as a class

class AppState {
    var isLoggedIn = false
}

let state1 = AppState()
let state2 = state1

state2.isLoggedIn = true

print(state1.isLoggedIn) // true

Both references point to the same object.


Example 3: Comparing memory behavior

Struct:

struct Point {
    var x: Int
    var y: Int
}

var p1 = Point(x: 0, y: 0)
var p2 = p1
p2.x = 10

print(p1.x) // 0

Class:

class PointClass {
    var x: Int
    var y: Int

    init(x: Int, y: Int) {
        self.x = x
        self.y = y
    }
}

var p1 = PointClass(x: 0, y: 0)
var p2 = p1
p2.x = 10

print(p1.x) // 10

The behavior changes entirely.


Common mistakes and how to fix them

Mistake 1: Expecting struct to share updates

What you might do:

var user1 = User(name: "Alex")
var user2 = user1
user2.name = "Sam"

Why it surprises you:

Structs are copied, so changes do not propagate.

Correct approach:

Use a class if you need shared state.


Mistake 2: Using class when value semantics are safer

What you might do:

class Coordinate {
    var x: Int
    var y: Int
}

Why it causes issues:

Shared references can lead to unintended side effects.

Correct approach:

struct Coordinate {
    var x: Int
    var y: Int
}

Use structs for simple values.


Troubleshooting

If changes to one variable affect another unexpectedly, check whether you used a class.

If you need inheritance but used a struct, switch to a class.

If copying large models feels expensive, remember Swift optimizes structs efficiently.

If you struggle with shared mutable state, prefer structs.


Quick recap

  • Structs are value types. Classes are reference types.
  • Struct copies are independent.
  • Class instances are shared.
  • Use struct for simple data models.
  • Use class for shared state or inheritance.
  • Choose based on behavior, not habit.