En este módulo, profundizaremos en el manejo avanzado de errores en Swift. Aprenderemos cómo definir y lanzar errores personalizados, cómo utilizar try?
y try!
, y cómo trabajar con errores en funciones asíncronas. Este conocimiento es crucial para escribir código robusto y manejable.
Contenido
Definición de Errores Personalizados
En Swift, los errores se definen mediante enumeraciones que adoptan el protocolo Error
. Esto permite crear tipos de error personalizados que se pueden lanzar y capturar.
Explicación
NetworkError
es una enumeración que adopta el protocoloError
.- Cada caso de la enumeración representa un tipo específico de error que puede ocurrir.
Lanzamiento y Captura de Errores
Para lanzar un error, se utiliza la palabra clave throw
. Para capturar errores, se utiliza una estructura do-catch
.
func fetchData(from url: String) throws { guard url == "https://valid.url" else { throw NetworkError.badURL } // Simulación de una solicitud de red let success = false if !success { throw NetworkError.requestFailed } } do { try fetchData(from: "https://invalid.url") } catch NetworkError.badURL { print("URL inválida.") } catch NetworkError.requestFailed { print("La solicitud falló.") } catch { print("Ocurrió un error desconocido.") }
Explicación
fetchData(from:)
es una función que puede lanzar errores (throws
).- Se utiliza
guard
para verificar la validez de la URL y lanzar un error si es inválida. - En el bloque
do
, se intenta ejecutarfetchData(from:)
y se capturan los errores específicos en los bloquescatch
.
Uso de try?
y try!
Swift proporciona dos formas adicionales de manejar errores: try?
y try!
.
try?
Convierte el resultado en un valor opcional. Si la función lanza un error, el resultado será nil
.
let data = try? fetchData(from: "https://invalid.url") if data == nil { print("Error al obtener los datos.") }
try!
Asume que la función no lanzará un error. Si lo hace, el programa se detendrá.
Explicación
try?
es útil cuando no te importa el error específico y solo necesitas saber si la operación tuvo éxito.try!
debe usarse con precaución, ya que puede causar que el programa se detenga si se lanza un error.
Propagación de Errores
Los errores pueden propagarse a través de múltiples niveles de funciones. Esto se hace declarando que una función puede lanzar errores (throws
) y utilizando try
al llamar a otras funciones que también pueden lanzar errores.
func performNetworkRequest() throws { try fetchData(from: "https://valid.url") } do { try performNetworkRequest() } catch { print("Error durante la solicitud de red: \(error)") }
Explicación
performNetworkRequest()
llama afetchData(from:)
y propaga cualquier error que se lance.- En el bloque
do
, se captura cualquier error lanzado porperformNetworkRequest()
.
Errores en Funciones Asíncronas
En Swift, las funciones asíncronas pueden manejar errores utilizando el mismo enfoque de throws
y try
.
func fetchDataAsync(from url: String, completion: @escaping (Result<String, Error>) -> Void) { DispatchQueue.global().async { do { try fetchData(from: url) completion(.success("Datos obtenidos con éxito.")) } catch { completion(.failure(error)) } } } fetchDataAsync(from: "https://invalid.url") { result in switch result { case .success(let data): print(data) case .failure(let error): print("Error: \(error)") } }
Explicación
fetchDataAsync(from:completion:)
es una función asíncrona que utiliza un bloque de finalización (completion
) para manejar el resultado.- Utiliza
DispatchQueue.global().async
para ejecutar la solicitud de red en un hilo de fondo. - El bloque de finalización recibe un
Result
que puede ser.success
o.failure
.
Ejercicios Prácticos
Ejercicio 1: Definir y Lanzar Errores Personalizados
Define una enumeración de errores personalizados para una función que valida direcciones de correo electrónico. Implementa la función y lanza errores apropiados.
enum EmailError: Error { case invalidFormat case domainNotAllowed } func validateEmail(_ email: String) throws { guard email.contains("@") else { throw EmailError.invalidFormat } guard email.hasSuffix("@example.com") else { throw EmailError.domainNotAllowed } } do { try validateEmail("[email protected]") } catch EmailError.invalidFormat { print("Formato de correo electrónico inválido.") } catch EmailError.domainNotAllowed { print("Dominio no permitido.") } catch { print("Ocurrió un error desconocido.") }
Ejercicio 2: Uso de try?
y try!
Modifica la función validateEmail
para usar try?
y try!
.
let emailValidation1 = try? validateEmail("[email protected]") if emailValidation1 == nil { print("Error al validar el correo electrónico.") } let emailValidation2 = try! validateEmail("[email protected]") print("Correo electrónico válido.")
Ejercicio 3: Propagación de Errores
Crea una función que llame a validateEmail
y propague cualquier error que se lance.
func checkEmail(_ email: String) throws { try validateEmail(email) } do { try checkEmail("[email protected]") } catch { print("Error al verificar el correo electrónico: \(error)") }
Conclusión
En esta sección, hemos explorado el manejo avanzado de errores en Swift. Aprendimos a definir y lanzar errores personalizados, utilizar try?
y try!
, propagar errores y manejar errores en funciones asíncronas. Estos conceptos son fundamentales para escribir código Swift robusto y manejable. En el próximo módulo, profundizaremos en la gestión de memoria en Swift.
Curso de Programación en Swift
Módulo 1: Introducción a Swift
- Introducción a Swift
- Configuración del Entorno de Desarrollo
- Tu Primer Programa en Swift
- Sintaxis y Estructura Básica
- Variables y Constantes
- Tipos de Datos
Módulo 2: Control de Flujo
Módulo 3: Funciones y Closures
- Definición y Llamada de Funciones
- Parámetros de Función y Valores de Retorno
- Closures
- Funciones de Orden Superior
Módulo 4: Programación Orientada a Objetos
Módulo 5: Swift Avanzado
Módulo 6: Swift y Desarrollo de iOS
- Introducción al Desarrollo de iOS
- Fundamentos de UIKit
- Storyboards y Interface Builder
- Redes en Swift
- Core Data
- Fundamentos de SwiftUI