En aquest tema, explorarem tècniques avançades per gestionar errors en Swift. La gestió d'errors és una part crucial del desenvolupament de programari, ja que permet als desenvolupadors manejar situacions inesperades de manera controlada i segura.

Continguts

Revisió de la Gestió d'Errors Bàsica

Abans d'endinsar-nos en tècniques avançades, fem una breu revisió de la gestió d'errors bàsica en Swift.

Declaració d'Errors

En Swift, els errors es declaren utilitzant el protocol Error. Aquí teniu un exemple:

enum FileError: Error {
    case fileNotFound
    case unreadable
    case encodingFailed
}

Llençar Errors

Per llençar un error, utilitzem la paraula clau throw:

func readFile(at path: String) throws -> String {
    // Simulació d'un error
    throw FileError.fileNotFound
}

Captura d'Errors

Els errors es capturen utilitzant una estructura do-catch:

do {
    let content = try readFile(at: "path/to/file")
    print(content)
} catch FileError.fileNotFound {
    print("El fitxer no s'ha trobat.")
} catch {
    print("S'ha produït un error: \(error).")
}

Errors Personalitzats

Crear errors personalitzats ens permet proporcionar informació més detallada sobre els errors que es produeixen.

Exemple d'Error Personalitzat

enum NetworkError: Error {
    case badURL
    case requestFailed(description: String)
    case unknown
}

Utilització d'Errors Personalitzats

func fetchData(from urlString: String) throws -> Data {
    guard let url = URL(string: urlString) else {
        throw NetworkError.badURL
    }
    
    // Simulació d'un error de sol·licitud
    throw NetworkError.requestFailed(description: "La sol·licitud ha fallat amb un codi d'estat 404.")
}

Propagació d'Errors

La propagació d'errors permet que una funció que llença errors pugui ser cridada des d'una altra funció que també llença errors.

Exemple de Propagació d'Errors

func performNetworkRequest() throws {
    try fetchData(from: "https://example.com")
}

do {
    try performNetworkRequest()
} catch NetworkError.badURL {
    print("URL incorrecta.")
} catch NetworkError.requestFailed(let description) {
    print("Error de sol·licitud: \(description).")
} catch {
    print("S'ha produït un error desconegut.")
}

Captura i Maneig d'Errors

Captura d'Errors Específics

Podem capturar errors específics i manejar-los de manera diferent:

do {
    try performNetworkRequest()
} catch NetworkError.badURL {
    print("URL incorrecta.")
} catch NetworkError.requestFailed(let description) {
    print("Error de sol·licitud: \(description).")
} catch {
    print("S'ha produït un error desconegut.")
}

Captura d'Errors Generals

Podem capturar errors generals utilitzant un bloc catch sense especificar el tipus d'error:

do {
    try performNetworkRequest()
} catch {
    print("S'ha produït un error: \(error).")
}

Errors i Funcions Asíncrones

Quan treballem amb funcions asíncrones, la gestió d'errors es complica una mica. Swift proporciona mecanismes per manejar errors en contextos asíncrons.

Exemple amb async i await

enum AsyncError: Error {
    case timeout
}

func fetchDataAsync() async throws -> Data {
    // Simulació d'un error asíncron
    throw AsyncError.timeout
}

func performAsyncRequest() async {
    do {
        let data = try await fetchDataAsync()
        print("Dades rebudes: \(data)")
    } catch AsyncError.timeout {
        print("La sol·licitud ha superat el temps d'espera.")
    } catch {
        print("S'ha produït un error: \(error).")
    }
}

Exercicis Pràctics

Exercici 1: Crear un Error Personalitzat

  1. Defineix un error personalitzat anomenat DatabaseError amb els casos connectionFailed i dataNotFound.
  2. Escriu una funció fetchDataFromDatabase que llença aquests errors.
  3. Escriu un bloc do-catch per capturar i manejar aquests errors.

Solució

enum DatabaseError: Error {
    case connectionFailed
    case dataNotFound
}

func fetchDataFromDatabase() throws -> String {
    // Simulació d'un error
    throw DatabaseError.connectionFailed
}

do {
    let data = try fetchDataFromDatabase()
    print("Dades rebudes: \(data)")
} catch DatabaseError.connectionFailed {
    print("La connexió a la base de dades ha fallat.")
} catch DatabaseError.dataNotFound {
    print("Les dades no s'han trobat.")
} catch {
    print("S'ha produït un error: \(error).")
}

Exercici 2: Manejar Errors en Funcions Asíncrones

  1. Defineix una funció asíncrona loadData que llença un error AsyncError.
  2. Escriu una funció performLoadData que crida loadData utilitzant await i maneja els errors.

Solució

enum AsyncError: Error {
    case timeout
}

func loadData() async throws -> String {
    // Simulació d'un error asíncron
    throw AsyncError.timeout
}

func performLoadData() async {
    do {
        let data = try await loadData()
        print("Dades carregades: \(data)")
    } catch AsyncError.timeout {
        print("La càrrega de dades ha superat el temps d'espera.")
    } catch {
        print("S'ha produït un error: \(error).")
    }
}

Conclusió

En aquesta secció, hem explorat tècniques avançades per gestionar errors en Swift, incloent la creació d'errors personalitzats, la propagació d'errors, la captura i maneig d'errors, i la gestió d'errors en funcions asíncrones. La gestió d'errors és una habilitat essencial per a qualsevol desenvolupador, ja que permet crear aplicacions més robustes i fiables. En el proper tema, ens endinsarem en la gestió de memòria en Swift.

© Copyright 2024. Tots els drets reservats