wandres.dev
EL MODELO DE TIPOS · structs, enums, protocolos

Enums con superpoderes

Los enums de Swift no son simples constantes: llevan valores asociados, métodos y encajan con el pattern matching de switch para modelar estados con precisión.

⏱ 14 min

Los enums de Swift están entre los más potentes de cualquier lenguaje. Van mucho más allá de una lista de opciones: modelan estados, transportan datos y, combinados con switch, hacen imposible olvidar un caso. Son una herramienta de diseño, no un detalle.

🎯 Al terminar esta lección sabrás
  • Enums básicos y raw values.
  • Valores asociados: enums que llevan datos.
  • Pattern matching exhaustivo con switch.
  • Métodos y CaseIterable.

Enum básico

Un conjunto cerrado de casos posibles:

enum Direccion {
    case norte, sur, este, oeste
}
let rumbo = Direccion.norte

Raw values

Cada caso puede tener un valor “crudo” asociado de forma fija (String, Int…):

enum Planeta: Int {
    case mercurio = 1, venus, tierra, marte   // 1, 2, 3, 4 automáticos
}
print(Planeta.tierra.rawValue)     // 3
let p = Planeta(rawValue: 4)       // Planeta? (opcional: podría no existir)

Valores asociados: la joya

Cada caso puede llevar datos distintos. Esto convierte al enum en una forma de modelar estados con su información:

enum Resultado {
    case exito(datos: String)
    case error(codigo: Int, mensaje: String)
    case cargando
}

let r = Resultado.error(codigo: 404, mensaje: "No encontrado")
Modela estados imposibles de romper

Piensa en un estado de carga con isLoading, data y error como tres variables sueltas: podrías tener isLoading = true y un error a la vez, un estado imposible que igualmente compila. Con un enum de valores asociados, cada estado es exclusivo por diseño: o estás cargando, o tienes exito(datos), o error(...), nunca dos a la vez. Haces que los estados inválidos sean irrepresentables. Es una de las técnicas de modelado más poderosas de Swift.

switch: pattern matching exhaustivo

El switch sobre un enum te obliga a cubrir todos los casos, y extrae los valores asociados:

switch r {
case .exito(let datos):
    print("OK: \(datos)")
case .error(let codigo, let mensaje):
    print("Error \(codigo): \(mensaje)")
case .cargando:
    print("Cargando…")
}
💡
Exhaustividad = seguridad futura

Si mañana añades un caso nuevo al enum (case timeout), todos los switch que no lo manejen dejarán de compilar hasta que lo cubras. El compilador te lleva de la mano a cada sitio que hay que actualizar. Olvidar un caso deja de ser posible.

Métodos en enums

Los enums pueden tener métodos y propiedades computadas:

enum Semaforo {
    case rojo, amarillo, verde

    var siguiente: Semaforo {
        switch self {
        case .rojo: .verde
        case .verde: .amarillo
        case .amarillo: .rojo
        }
    }
}
print(Semaforo.rojo.siguiente)   // verde

CaseIterable

Añade CaseIterable y obtienes una colección con todos los casos, ideal para menús y pickers:

enum Tema: String, CaseIterable {
    case claro, oscuro, sistema
}
for tema in Tema.allCases {
    print(tema.rawValue)   // claro, oscuro, sistema
}
⚔️ Modela con enums
  1. Crea un enum EstadoPedido con casos pendiente, enviado(tracking: String) y entregado.
  2. Escribe un switch que imprima un mensaje distinto por caso, extrayendo el tracking.
  3. Añade una propiedad computada esFinal que devuelva true solo para entregado.
  4. Haz un enum CaseIterable y recorre allCases.