iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Structs

Swift structs are value types — copied on assignment, no reference identity. Use them for data: models, view state, value objects. The compiler synthesises memberwise initialisers, Equatable, and Codable.

Memberwise init, mutating, protocols

EXAMPLE
// 1) Basic struct
struct Point {
    var x: Double
    var y: Double
}

let p = Point(x: 1, y: 2)         // memberwise init auto-generated

// 2) Value semantics — copy, not reference
var a = Point(x: 1, y: 2)
var b = a                          // copy
b.x = 99
print(a.x)                         // 1 — unchanged

// 3) Mutating method — required when modifying self
struct Counter {
    var value = 0
    mutating func inc() { value += 1 }
}

var c = Counter()
c.inc()                            // c.value == 1
// let cc = Counter(); cc.inc()    // ERROR — can't mutate a let

// 4) Computed properties
struct Rect {
    var width: Double
    var height: Double
    var area: Double { width * height }
    var aspect: Double {
        get { width / height }
        set { width = height * newValue }
    }
}

// 5) Auto-conformances when possible — Equatable, Hashable, Codable
struct User: Equatable, Hashable, Codable {
    let id: UUID
    var name: String
    var email: String
}

// Free synthesis: ==, hash(into:), Codable encode/decode
let u1 = User(id: UUID(), name: "Ada", email: "a@x.com")
let u2 = u1
print(u1 == u2)                    // true
let json = try JSONEncoder().encode(u1)
let back = try JSONDecoder().decode(User.self, from: json)

// 6) Custom initialiser
struct Money {
    let amount: Decimal
    let currency: String
    init(_ amount: Decimal, in currency: String = "AUD") {
        self.amount   = amount
        self.currency = currency
    }
}
let price = Money(9.99)

// 7) Generic struct
struct Stack<Element> {
    private var items: [Element] = []
    mutating func push(_ e: Element) { items.append(e) }
    mutating func pop() -> Element?  { items.popLast() }
    var top: Element?                 { items.last }
    var count: Int                    { items.count }
}

var nums = Stack<Int>()
nums.push(1); nums.push(2)

// 8) Extensions — add methods to a struct from outside
extension Point {
    func distance(to other: Point) -> Double {
        hypot(x - other.x, y - other.y)
    }
}
let d = p.distance(to: Point(x: 4, y: 6))

// 9) Conform to a protocol
protocol Describable { var description: String { get } }

struct Product: Describable {
    let name: String
    let price: Double
    var description: String { "\(name) — $\(price)" }
}

// 10) Property wrappers — declarative property behaviour
@propertyWrapper
struct Capitalised {
    private var value: String = ""
    var wrappedValue: String {
        get { value }
        set { value = newValue.capitalized }
    }
}

struct Person {
    @Capitalised var name: String
}

var alice = Person(name: "ada")
print(alice.name)                  // "Ada"

// 11) Struct vs class — when to choose which
// Struct (value): data, model layer, immutable-by-default, no shared identity needed
// Class (reference): need shared identity, reference cycles via @State / observation, ObjC interop
// Default to struct; reach for class when you NEED reference semantics.

// 12) Copy-on-write — efficient large value types
// Stdlib types (Array, Dictionary, String, Set) are structs with copy-on-write
// Assigning is O(1); copy only happens when mutated AND the storage has another owner.

Why it matters

Default to struct in Swift. Value semantics + auto-conformance + copy-on-write give you safety and performance for free; switch to class only when reference identity is genuinely needed.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
struct User {
    var name: String
    var age: Int
    mutating func happyBirthday() { age += 1 }
}
var u = User(name: "Ada", age: 36)
u.happyBirthday()
Try it Yourself »

Exercise

Method that mutates self on a struct.

func bump() { age += 1 }

Test yourself

Q1. Structs in Swift are…
Q2. Inside a mutating method on a struct you need…
Q3. Prefer structs over classes when…

Discussion

Loading…