Menu
Coddy logo textTech

Propagación de errores

Parte de la sección Lógica y Flujo del Journey de Swift de Coddy — lección 47 de 56.

Una función que lanza errores puede llamar a otras funciones que lanzan errores. El error se propaga automáticamente hasta el do/catch más cercano, sin necesidad de relanzarlo manualmente.

enum AuthError: Error { case badUser, badPass }

func loadUser(_ name: String) throws -> String {
    if name.isEmpty { throw AuthError.badUser }
    return name
}

func login(_ name: String, _ pass: String) throws -> String {
    let u = try loadUser(name)            // propaga el error
    if pass.count < 4 { throw AuthError.badPass }
    return "hello \(u)"
}

do {
    print(try login("", "abcd"))
} catch AuthError.badUser {
    print("missing user")
} catch AuthError.badPass {
    print("weak password")
}

Lee de arriba a abajo: login llama a loadUser con try. Si loadUser lanza un error, el error se salta el cuerpo de login y cae en el catch externo. Escribes cada paso para que falle rápido y dejas que quien llama decida qué hacer.

challenge icon

Desafío

Intermedio

Construye una pequeña canalización de dos pasos que lanzan errores.

Define StepError: Error con dos casos: negative, tooBig.

Define parseSafe(_ s: String) throws -> Int: lanza .negative cuando el entero analizado es menor que 0, de lo contrario lo devuelve. (Asume que la entrada se analiza correctamente, ya has manejado eso en otro lugar).

Define capStrict(_ n: Int) throws -> Int: lanza .tooBig cuando n > 100, de lo contrario devuelve n.

Define processStep(_ s: String) throws -> Int que llame a parseSafe y luego a capStrict, permitiendo que cualquier error se propague.

Lee una sola línea de entrada: una lista de cadenas separadas por comas. Para cada una, llama a processStep en un bloque do/catch e imprime una línea:

  • ok: <n> en caso de éxito
  • negative cuando parseSafe lanzó un error
  • too big cuando capStrict lanzó un error

Para la entrada 10,-1,200,42, la salida es:

ok: 10
negative
too big
ok: 42

Hoja de referencia

Una función que lanza errores puede llamar a otras funciones que lanzan errores con try. Los errores se propagan automáticamente hasta el do/catch más cercano:

enum AuthError: Error { case badUser, badPass }

func loadUser(_ name: String) throws -> String {
    if name.isEmpty { throw AuthError.badUser }
    return name
}

func login(_ name: String, _ pass: String) throws -> String {
    let u = try loadUser(name)   // el error se propaga si se lanza
    if pass.count < 4 { throw AuthError.badPass }
    return "hello \(u)"
}

do {
    print(try login("", "abcd"))
} catch AuthError.badUser {
    print("missing user")
} catch AuthError.badPass {
    print("weak password")
}

Si loadUser lanza un error, la ejecución se salta el resto de login y llega directamente al catch externo. No es necesario volver a lanzar el error manualmente.

Pruébalo tú mismo

let parts = readLine()!.components(separatedBy: ",")

// TODO: enum StepError; parseSafe; capStrict; processStep;
// para cada parte, hacer/intentar processStep, capturar cada rama, imprimir
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Lógica y Flujo