Manejo de errores en Swift: try/catch y más allá — guía completa
El manejo de errores es uno de los temas clave en el desarrollo para iOS y macOS. En el lenguaje Swift se implementa un sistema de gestión de fallos potente y elegante que va mucho más allá del simple try/catch. Comprender estos mecanismos permite escribir código robusto, predecible y seguro. En este artículo analizaremos todos los aspectos: desde la declaración básica de errores hasta técnicas avanzadas con valores opcionales y desinicializadores.
Fundamentos: el protocolo Error y la palabra clave throws
En Swift, cualquier error debe cumplir con el protocolo Error. Normalmente se utilizan enumeraciones (enum) para ello. Veamos un ejemplo simple: verificación de contraseña:
enum PasswordError: Error { case tooShort case missingDigit case missingUppercase}
func validatePassword(_ password: String) throws { guard password.count >= 8 else { throw PasswordError.tooShort } guard password.rangeOfCharacter(from: .decimalDigits) != nil else { throw PasswordError.missingDigit } guard password.rangeOfCharacter(from: .uppercaseLetters) != nil else { throw PasswordError.missingUppercase } print("Contraseña válida")}La palabra clave throws en la declaración de la función informa al compilador de que la ejecución puede ser interrumpida por un error. Llamar a dicha función requiere una sintaxis especial.
La construcción do-catch y la palabra clave try
Para manejar errores potenciales se utiliza el bloque do-catch con la marca try antes de la llamada:
do { try validatePassword("Hello123") print("¡Éxito!")} catch PasswordError.tooShort { print("Error: la contraseña es demasiado corta")} catch PasswordError.missingDigit { print("Error: la contraseña no tiene dígito")} catch PasswordError.missingUppercase { print("Error: la contraseña no tiene mayúscula")} catch { print("Error desconocido: \\(error)")}Observe el último bloque catch — captura cualquier error no contemplado anteriormente. Este es un requisito obligatorio: el compilador de Swift verifica que todos los errores posibles sean manejados.
try? y try! — variantes simplificadas de manejo
A veces no se necesita un control completo sobre los errores. Swift ofrece dos variantes abreviadas:
- try? — convierte el error en un valor opcional
nil. Si no hay error, devuelve el resultado envuelto enOptional. - try! — afirma que no habrá error. Si ocurre, la aplicación termina abruptamente (runtime crash).
// try? — ignorar el error de forma seguraif let _ = try? validatePassword("weak") { print("La contraseña pasó la verificación")} else { print("La contraseña no pasó")}
// try! — solo si está 100% segurolet result = try! validatePassword("StrongPass1") // Crash si la contraseña no es válidaUse try! solo en situaciones donde el error sea teóricamente imposible (por ejemplo, al cargar un recurso incluido en el bundle de la aplicación).
Técnicas avanzadas: rethrows, defer y Result
Re-lanzamiento de errores (rethrows)
La palabra clave rethrows se aplica a funciones de orden superior que reciben un closure capaz de lanzar un error. La función en sí no lanza el error, sino que lo transmite desde el closure:
func processItems(_ items: [String], using validator: (String) throws -> Void) rethrows { for item in items { try validator(item) }}
// Usodo { try processItems(["Hello", "World123"], using: validatePassword)} catch { print("Error de procesamiento: \\(error)")}Esto permite escribir funciones envoltorio flexibles sin duplicar el código de manejo de errores.
Blogs
Book Recommendations
Leer también
lateinit en Kotlin: cómo verificar si una variable está inicializada
Las mejores IDE y herramientas para desarrollo en C++: guía completa
API GraphQL con Java: tutorial paso a paso para principiantes
Long-Polling, WebSockets, SSE y Comet en PHP: guía completa con código
Optimización del rendimiento de aplicaciones Rust: para principiantes
Blogs
Book Recommendations
Leer también
Las mejores IDE y herramientas para desarrollo en C++: guía completa
API GraphQL con Java: tutorial paso a paso para principiantes