DEV Community

Aleksei Barinov
Aleksei Barinov

Posted on

Structs in Swift

Hello everyone, this is Aleksei Barinov and you’re reading my first longread series on interview questions for iOS developer positions. Today, we’ll discuss one of the most frequently asked questions — and that is: tell me everything you know about structures. This question may be asked on its own, or as part of a broader question like “what is the difference between structures and classes?” But either way, the main goal is to share everything you know about this type of data. So let’s try to do that together!

The Foundation: What Are Structs?

At their core, structs are value types that encapsulate related data and behavior. When you create a struct instance and assign it to another variable, Swift creates an independent copy rather than a shared reference. This fundamental property drives every design decision and performance characteristic that makes structs the cornerstone of modern Swift development.

Consider a simple struct representing an rock anthem:

struct RockSong {
    let title: String
    let artist: String
    let year: Int
    var chartPosition: Int

    func description() -> String {
        return "\(title) by \(artist) (\(year))"
    }
}
Enter fullscreen mode Exit fullscreen mode

Creating and copying this struct demonstrates value semantics in action:

var song1 = RockSong(

title: "Sweet Child O' Mine",

 artist: "Guns N' Roses",

 year: 1987,

 chartPosition: 1

)

var song2 = song1
song2.chartPosition = 5

print(song1.chartPosition) *// Still 1*
print(song2.chartPosition) *// Now 5*
Enter fullscreen mode Exit fullscreen mode

The two instances remain completely independent, just as two vinyl records of the same album exist as separate physical objects.

Value Semantics vs. Reference Semantics:

Value types contain their data directly; reference types point to data stored elsewhere.

Value Types (Structs, Enums, Tuples)

  • Stored on the stack for efficiency (it still may be stored in heap, static & global memory)
  • Each instance owns its data
  • Copies are independent and inexpensive
  • The structure's behavior actually helps prevent some multithreading issues.
  • No memory management overhead

Reference Types (Classes)

  • Stored on the heap with pointer indirection
  • Multiple references share the same instance
  • Copies share state, creating potential side effects
  • Require ARC (Automatic Reference Counting)
  • Risk of retain cycles and memory leaks

This distinction becomes critical when modeling shared state versus independent entities.

Comparison: Structs vs. Classes

Aspect Struct Class
Type Semantics Value type Reference type
Memory Location Stack (usually) Heap (always)
Copy Behavior Independent copies Shared references
Inheritance Not supported Single inheritance
Deinitializer Not available deinit supported
Reference Counting Not applicable ARC managed
Identity Operator No === operator === checks instance identity
Mutability Requires mutating keyword for method changes Always mutable
Thread Safety Inherently safe Requires careful synchronization

When to Choose Structs

Structs shine when you need independent, lightweight data. Use them for:

  • Model objects (songs, race results, configuration)
  • Data transfer objects (API responses)
  • View models
  • SwiftUI view data
  • Mathematical entities (coordinates, vectors)
  • Immutable configurations

When to Choose Classes

Classes remain appropriate for shared, mutable state:

  • Managing external resources (file handles, network connections)
  • UIKit view controllers and views
  • Database connections (Core Data, Realm)
  • Objects requiring identity (same instance must be shared)
  • Complex inheritance hierarchies

Advanced Concepts Interviewers Love

Copy-on-Write Optimization

Swift collections like Array and Dictionary use copy-on-write to avoid expensive copies until mutation occurs.

 

var setlist1 = ["Welcome to the Jungle", "Paradise City", "Sweet Child O' Mine"]
var setlist2 = setlist1 *// No copy yet—both reference same memory*

setlist2.append("November Rain") *// Copy occurs here*
Enter fullscreen mode Exit fullscreen mode

This optimization makes structs efficient even for large data structures. When a struct contains reference types, you must implement copy-on-write manually to maintain value semantics.

Memory Management Deep Dive

Structs live on the stack, making them cache-friendly and allocation-cheap. The stack's LIFO nature means structs are automatically deallocated when they go out of scope—no garbage collection or reference counting overhead.

Envision a Formula 1 pit stop sequence:

struct PitStopData {
    let driver: String
    var lapTime: Double
    var tireCompound: String
}

func recordPitStop() {
    let stop = PitStopData(driver: "Senna", lapTime: 8.2, tireCompound: "Soft")
    *// Struct exists only during function execution// Automatically cleaned up when function returns*
}
Enter fullscreen mode Exit fullscreen mode

The struct disappears automatically, just as a pit crew's specific stop data becomes irrelevant once the car rejoins the track.

The Mutating Keyword

By default, struct methods cannot modify properties. The mutating keyword signals intent to change the instance, which actually replaces the entire instance with a modified copy:

struct F1ChampionshipStanding {
    var driver: String
    var points: Int

    mutating func addPoints(_ newPoints: Int) {
        points += newPoints
        *// Behind the scenes: self = F1ChampionshipStanding(driver: self.driver, points: self.points + newPoints)*
    }
}
Enter fullscreen mode Exit fullscreen mode

This mechanism preserves value semantics while allowing necessary mutations.

Protocol Conformance and Composition

Structs excel at protocol-oriented programming, a Swift paradigm that favors composition over inheritance. They can conform to multiple protocols without inheritance complexity:

protocol Chartable {
    func peakPosition() -> Int
}

protocol Streamable {
    var playCount: Int { get }
}

struct RockHit: Chartable, Streamable {
    let title: String
    let peakChart: Int
    let plays: Int

    func peakPosition() -> Int {
        return peakChart
    }

    var playCount: Int {
        return plays
    }
}
Enter fullscreen mode Exit fullscreen mode

That’s pretty much it for now!

Share in the comments what other questions about structs you were asked during interviews and how you answered them — your experience can help other candidates.

Make sure to subscribe to my Telegram channel so you don’t miss new articles and future updates.

By the way, I made an app for MacOS to help you prepare for interviews for iOS developer positions. You can also find out more about this app in my Telegram channel.

See you soon in the next post!

Top comments (0)