Open menu with table of contents Swift: Structs vs. Classes
Logo of Stuttgart Media University for light theme Logo of Stuttgart Media University for dark theme
Mobile Application Development 2

Swift: Structs vs. Classes

Understanding the difference, their purpose, benefits, and downsides.

Stuttgart Media University

Meme 1

1 What are Structs and Classes?

In Swift, both structs and classes are general-purpose, flexible constructs that become the building blocks of your program’s code. You use them to create custom data types.

Struct Definition:

struct Resolution {
    var width = 0
    var height = 0
}

Class Definition:

class VideoMode {
    var resolution = Resolution()
    var frameRate = 0.0
    var name: String?
}

2 Key Difference: Value Type vs. Reference Type

This is the most fundamental difference between structs and classes.

Structs are Value Types:

  • When a struct is copied (assigned to a new variable or passed to a function), a new, independent copy of the data is created.
  • Changes to one copy do not affect the other.

Classes are Reference Types:

  • When a class instance is copied, a new reference (or pointer) to the same underlying object is created.
  • Both references point to the same single instance in memory. Changes made through one reference will be visible through the other.

3 Structs: Value Type in Action

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

var point1 = Point(x: 1, y: 2)
var point2 = point1 // A copy is made

point2.x = 100

print(point1.x) // Output: 1
print(point2.x) // Output: 100

point1 remains unchanged because point2 is a separate copy.

4 Classes: Reference Type in Action

class Person {
    var name: String
    init(name: String) { self.name = name }
}

var person1 = Person(name: "Alice")
var person2 = person1 // A new reference is made

person2.name = "Bob"

print(person1.name) // Output: "Bob"
print(person2.name) // Output: "Bob"

person1's name changes because both variables refer to the same object.

5 Other Key Differences

Feature Structs Classes
Type Value Type Reference Type
Inheritance Cannot inherit Can inherit from other classes
Initializers Automatic memberwise init Must create init manually
Deinitializers Cannot have deinit Can have deinit
Mutability let instances are immutable let instances can have mutable properties (if var)
Memory Stored on the Stack (faster) Stored on the Heap (slower, requires reference counting)

6 Structs: Benefits and Downsides

Benefits:

  • Predictable and Safe: Great for multi-threaded environments as there's no risk of one thread changing data while another is using it (no side effects).
  • Performance: Faster allocation and access because they are typically stored on the stack.
  • Simplicity: No need to worry about memory management complexities like retain cycles.
  • Automatic Initializer: You get a free memberwise initializer.

Downsides:

  • No Inheritance: Cannot be used to model "is-a" relationships (e.g., a Car is a Vehicle).
  • Copying Overhead: Can be less efficient if the struct holds a large amount of data, as the entire object is copied.

7 Classes: Benefits and Downsides

Benefits:

  • Inheritance: Allows you to create hierarchies of objects, reducing code duplication.
  • Shared State: Useful when you need multiple parts of your app to share and modify the same piece of information (e.g., a user profile).
  • Objective-C Interoperability: Required for working with older Apple APIs.
  • deinit: Allows for custom cleanup logic when an object is destroyed.

Downsides:

  • Complexity: Slower allocation (heap) and added overhead of reference counting.
  • Risk of Side Effects: Unintended changes can occur since multiple references can modify the same object. This can lead to bugs that are hard to track.
  • Memory Leaks: Risk of creating "retain cycles" where two objects hold strong references to each other and are never deallocated.

8 When to Use Which? The Golden Rule

The Swift team at Apple provides a clear recommendation:

Start with a struct.

Use structs by default, especially for modeling data that doesn't have a distinct identity or lifecycle. Examples include coordinates (CGPoint), sizes (CGSize), or custom data models passed around your app.

Use a class only when you need features that structs don't provide:

  1. You need Inheritance.
  2. You need to control Identity (e.g., you need to know that two variables refer to the exact same object).
  3. You need Objective-C interoperability.
  4. You need a deinit to manage a resource.

For SwiftUI, this is even more true. Most of your data models should be structs.

9 Summary

  • Structs are value types (copies). They are simple, fast, and safe. Use them as your default choice for custom data.
  • Classes are reference types (pointers). They support inheritance and allow for shared, mutable state. Use them when you specifically need their unique features.

Understanding this distinction is key to writing clean, safe, and efficient Swift code.

Meme 2