Swift Enum Deep Dive: RawValue Initialization, Implicit Values & Recursion
  • July 24, 2025

 


Raw Values

A raw value is a constant of a primitive type (like Int, String, or Double) that you assign to each enum case. This lets you convert between the enum and its underlying primitive representation.

enum Weekday: Int {
    case monday = 1
    case tuesday = 2
    case wednesday = 3
    case thursday = 4
    case friday = 5
    case saturday = 6
    case sunday = 7
}

print(Weekday.friday.rawValue)  // 5
  • Declare the raw-value type after the enum name (: Int).
  • Each case must have a unique raw value of that type.
  • Swift synthesizes a failable initializer init?(rawValue:) for you.

Implicitly Assigned Raw Values

When your raw-value type is Int or String, Swift can fill in missing values automatically.

Integer enums

If you give the first case an Int raw value, subsequent cases increment by one:

enum LogLevel: Int {
    case debug = 1
    case info, warning, error
}

print(LogLevel.warning.rawValue)  // 3

Here, info is 2, warning 3, and error 4 automatically.

String enums

If you omit raw values on a String enum, each case’s raw value defaults to its own name:

enum Planet: String {
    case mercury, venus, earth, mars
}

print(Planet.earth.rawValue)  // "earth"

This is especially handy for coding keys, API parameters, or user-facing strings.


Initializing from a Raw Value

Use the synthesized initializer init?(rawValue:) to attempt converting a primitive into your enum:

if let day = Weekday(rawValue: 3) {
    print("Day 3 is \(day)")  // "Day 3 is wednesday"
} else {
    print("No matching weekday")
}

// Failable: returns nil for out-of-range or mismatched values
let maybeDay = Weekday(rawValue: 10)  // nil

Because it’s failable (init?), you must unwrap safely (if let, guard let, etc.).


Recursive Enumerations

A recursive enum is one whose cases can hold instances of the same enum type—ideal for tree-like data structures. Mark the recursive cases with the indirect keyword:

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)
}

You can also mark the entire enum as indirect:

indirect enum Expr {
    case number(Int)
    case plus(Expr, Expr)
    case times(Expr, Expr)
}

Evaluating a Recursive Enum

Define a function that walks the structure:

func evaluate(_ expr: ArithmeticExpression) -> Int {
    switch expr {
    case .number(let value):
        return value
    case .addition(let left, let right):
        return evaluate(left) + evaluate(right)
    case .multiplication(let left, let right):
        return evaluate(left) * evaluate(right)
    }
}

// Build ((5 + 4) * 2)
let expr = ArithmeticExpression.multiplication(
    .addition(.number(5), .number(4)),
    .number(2)
)
print(evaluate(expr))  // 18
  • The indirect keyword tells Swift to insert a level of indirection so the enum can refer to itself.
  • Recursive enums let you model nested, hierarchical data cleanly and safely.

Tips & Gotchas

  • Raw-value enums are best when each case has a fixed, primitive mapping (e.g., HTTP status codes, JSON keys).
  • Don’t mix associated values on a raw-value enum—Swift disallows it.
  • Use guard let x = MyEnum(rawValue: value) to validate external input.
  • Recursive enums can be memory-heavy; consider class-based trees or value-indirect structs for very deep structures.
YOU MIGHT ALSO LIKE...
🧭 NavigationKit

NavigationKit is a lightweight library which makes SwiftUI navigation super easy to use. 💻 Installation 📦 Swift Package Manager Using Swift Package Manager, add ...

swiftui-navigation-stack

An alternative SwiftUI NavigationView implementing classic stack-based navigation giving also some more control on animations and programmatic navigation. NavigationStack Installation ...

Stinsen

Simple, powerful and elegant implementation of the Coordinator pattern in SwiftUI. Stinsen is written using 100% SwiftUI which makes it ...

SwiftUI Router

With SwiftUI Router you can power your SwiftUI app with path-based routing. By utilizing a path-based system, navigation in your app becomes ...

FlowStacks

This package takes SwiftUI's familiar and powerful NavigationStack API and gives it superpowers, allowing you to use the same API not just ...