Swift Enums

An enum (short for enumeration) defines a type with a fixed set of named cases. Use an enum when a variable should only ever hold one of a known group of values. Think of an enum like a light switch — it can only be ON or OFF, never something in between.

Basic Enum

enum Direction {
    case north
    case south
    case east
    case west
}

var heading = Direction.north
heading = .east   // Swift infers the type, so you can drop "Direction"

print(heading)   // Output: east

Enum in a switch Statement

Enums and switch are a natural pair. Swift requires every case to be covered, so you cannot accidentally miss one.

let move = Direction.south

switch move {
case .north:
    print("Moving north")
case .south:
    print("Moving south")
case .east:
    print("Moving east")
case .west:
    print("Moving west")
}
// Output: Moving south

Diagram: Enum as a Sealed Group

enum Direction
+-------+-------+------+------+
| north | south | east | west |
+-------+-------+------+------+
   ↑
Only one of these four can be the value at any time.

Enum with Raw Values

Cases can carry a raw value of a fixed type. Each case maps to a specific underlying value.

enum Planet: Int {
    case mercury = 1
    case venus   = 2
    case earth   = 3
    case mars    = 4
}

let home = Planet.earth
print(home.rawValue)   // Output: 3

// Create from raw value (returns optional)
if let p = Planet(rawValue: 4) {
    print(p)   // Output: mars
}

String Raw Values

enum Season: String {
    case spring = "Spring"
    case summer = "Summer"
    case autumn = "Autumn"
    case winter = "Winter"
}

let now = Season.summer
print(now.rawValue)   // Output: Summer

Enum with Associated Values

Associated values attach extra data to a specific case. Each case can carry different types of data — like a labeled package.

enum Notification {
    case message(from: String, text: String)
    case call(from: String, duration: Int)
    case reminder(title: String)
}

let alert = Notification.message(from: "Alice", text: "Hello!")

switch alert {
case .message(let sender, let text):
    print("Message from \(sender): \(text)")
case .call(let caller, let seconds):
    print("Call from \(caller) lasting \(seconds)s")
case .reminder(let title):
    print("Reminder: \(title)")
}
// Output: Message from Alice: Hello!

Diagram: Associated Values

enum Notification
.message ──→ (from: String, text: String)
.call    ──→ (from: String, duration: Int)
.reminder──→ (title: String)

Each case carries its own shape of data.

Enum Methods

Enums can contain methods just like structs and classes.

enum Coin: Double {
    case penny   = 0.01
    case nickel  = 0.05
    case dime    = 0.10
    case quarter = 0.25

    func description() -> String {
        return "This coin is worth \(rawValue) dollars."
    }
}

let c = Coin.quarter
print(c.description())   // Output: This coin is worth 0.25 dollars.

Enum Computed Properties

enum TrafficLight {
    case red, yellow, green

    var instruction: String {
        switch self {
        case .red:    return "Stop"
        case .yellow: return "Slow down"
        case .green:  return "Go"
        }
    }
}

let light = TrafficLight.green
print(light.instruction)   // Output: Go

Mutating Methods in Enums

An enum method can change the value of self when marked mutating.

enum PowerMode {
    case off, standby, on

    mutating func turnOn() {
        self = .on
    }

    mutating func turnOff() {
        self = .off
    }
}

var mode = PowerMode.standby
mode.turnOn()
print(mode)   // Output: on

Recursive Enums with indirect

An enum case can refer to itself using the indirect keyword. This is useful for tree structures and linked lists.

indirect enum MathExpr {
    case number(Int)
    case add(MathExpr, MathExpr)
    case multiply(MathExpr, MathExpr)
}

func evaluate(_ expr: MathExpr) -> Int {
    switch expr {
    case .number(let n):
        return n
    case .add(let a, let b):
        return evaluate(a) + evaluate(b)
    case .multiply(let a, let b):
        return evaluate(a) * evaluate(b)
    }
}

let expr = MathExpr.add(.number(3), .multiply(.number(4), .number(5)))
print(evaluate(expr))   // Output: 23  (3 + 4*5)

Summary

Enums define a type with a closed set of named cases. They can carry raw values for simple mappings or associated values for richer attached data. Enums support methods, computed properties, and mutating methods. Pair them with switch for exhaustive, compile-time-checked branching logic.

Leave a Comment

Your email address will not be published. Required fields are marked *