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

structUser {
varname:String
}

varuser1=User(name:"Alex")
varuser2=user1

user2.name="Sam"

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

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

Class example

classUser {
varname:String

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

varuser1=User(name:"Alex")
varuser2=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:

structProduct {
vartitle:String
varprice: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:

classSessionManager {
varisLoggedIn=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.

classAnimal {
funcspeak() {
print("Animal sound")
    }
}

classDog:Animal {
overridefuncspeak() {
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.

structCounter {
varvalue:Int

mutatingfuncincrement() {
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

structSettings {
varisDarkMode:Bool
varfontSize:Int
}

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

Each copy of Settings is independent.


Example 2: Shared manager as a class

classAppState {
varisLoggedIn=false
}

letstate1=AppState()
letstate2=state1

state2.isLoggedIn=true

print(state1.isLoggedIn)// true

Both references point to the same object.


Example 3: Comparing memory behavior

Struct:

structPoint {
varx:Int
vary:Int
}

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

print(p1.x)// 0

Class:

classPointClass {
varx:Int
vary:Int

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

varp1=PointClass(x:0,y:0)
varp2=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:

varuser1=User(name:"Alex")
varuser2=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:

classCoordinate {
varx:Int
vary:Int
}

Why it causes issues:

Shared references can lead to unintended side effects.

Correct approach:

structCoordinate {
varx:Int
vary: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.