Swift Cheatsheet

Types & Protocols

Use this Swift reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Structs vs classes

struct Point {                   // value type, copied on assignment
    var x = 0
    var y = 0                    // memberwise init is free: Point(x: 1, y: 2)
}

final class Counter {            // reference type, shared on assignment
    var value = 0
    init(value: Int = 0) { self.value = value }
    func inc() { value += 1 }
    deinit { print("gone") }
}
struct / enumclass
SemanticsValue, copiedReference, shared
InheritanceNo (protocols only)Yes
deinitNoYes
Memberwise initGeneratedWrite your own
Identity (===)NoYes
Default choiceYesOnly for identity, inheritance, or shared mutable state

Computed properties, observers, lazy

struct Circle {
    var radius: Double

    var area: Double {                 // computed, read-only
        .pi * radius * radius
    }

    var diameter: Double {             // computed get/set
        get { radius * 2 }
        set { radius = newValue / 2 }
    }
}

final class Slider {
    var value = 0 {
        willSet { print("will become \(newValue)") }
        didSet { print("was \(oldValue), now \(value)") }
    }
    static let shared = Slider()       // type-level property
}

final class Report {
    let data: [Int]
    init(data: [Int]) { self.data = data }
    lazy var sortedData: [Int] = data.sorted()   // computed once, on first access
}

Access control

LevelVisible from
openAnywhere, and subclassable/overridable outside the module (classes)
publicAnywhere, but not subclassable outside the module
packageAny module in the same package (Swift 5.9+)
internalSame module (the default)
fileprivateSame source file
privateEnclosing declaration, plus its extensions in the same file
public struct Account {
    public private(set) var balance = 0    // read anywhere, write internally
    private var pin = "0000"

    public mutating func deposit(_ n: Int) { balance += n }
}

Enums

enum Direction: String, CaseIterable {     // raw values + iteration
    case north, south, east, west
}
Direction.north.rawValue                   // "north"
Direction(rawValue: "east")                // Optional(.east)
Direction.allCases.count                   // 4

enum LoadState {                           // associated values
    case idle
    case loading(progress: Double)
    case failed(message: String)
}

let state = LoadState.loading(progress: 0.4)
switch state {
case .idle: print("idle")
case .loading(let p): print("\(Int(p * 100))%")
case .failed(let msg): print(msg)
}

indirect enum Tree {                       // recursive payloads need indirect
    case leaf(Int)
    case node(Tree, Tree)
}

Protocols and default implementations

protocol Named {
    var name: String { get }
    func describe() -> String
}

extension Named {
    func describe() -> String { "I am \(name)" }   // default implementation
}

struct User: Named { let name: String }
User(name: "Ada").describe()               // "I am Ada"

struct Cell: Equatable, Hashable, Codable {  // conformances synthesized
    var x: Int
    var y: Int
}

Equatable, Hashable, and Codable are synthesized automatically when every stored property conforms. Add Comparable by implementing static func < .

some vs any (opaque vs existential)

protocol Shape { var area: Double { get } }

struct Square: Shape {
    var side: Double
    var area: Double { side * side }
}

func makeShape() -> some Shape {           // opaque: one hidden concrete type
    Square(side: 2)
}

let shapes: [any Shape] = [Square(side: 2), Square(side: 3)]   // boxed existentials
let total = shapes.reduce(0) { $0 + $1.area }

some keeps the concrete type known to the compiler: static dispatch, no boxing, required for SwiftUI body. any erases the type into a box: heterogeneous storage and flexible APIs, with a small runtime cost. Prefer generics or some in hot paths, write any explicitly for existentials.

Macros and @Observable

import Observation

@Observable
final class CartModel {                    // Swift 5.9+ macro
    var items: [String] = []
    var total = 0
}

@Observable replaces the older ObservableObject + @Published pattern for SwiftUI state. Attached macros (@Observable, #Predicate, custom ones) expand at compile time and are inspectable via Xcode's "Expand Macro".