Gestion des erreurs en Swift

Introduction aux erreurs en Swift

En programmation Swift, les erreurs permettent de signaler et gérer des conditions inattendues qui peuvent survenir pendant l'exécution du programme. Elles font partie d'un mécanisme de gestion des erreurs qui aide un programme à identifier le type d'erreur et à y répondre de manière appropriée.

Création d'un type d'erreur

Le protocole Error est intégré dans Swift, ce qui signifie que n'importe quel type peut représenter une condition d'erreur en s'y conformant. Pour représenter des types d'erreur liés, il est préférable d'utiliser une énumération. Par exemple, on peut modéliser des situations d'erreurs qui peuvent survenir lors de l'utilisation d'une voiture :

enum CarError: Error {
    case noFuel
    case brokenEngine
    case check(fluid: String)
}

Émettre des erreurs

Si une fonction ou une méthode contient du code susceptible de générer une erreur, elle doit être déclarée avec le mot-clé throws. Cela permet à l'erreur de remonter jusqu'à la fonction appelante, qui pourra alors gérer cette erreur. Voici un exemple de fonctions qui émettent des erreurs :

func throwFunc() throws {}
func throwFunc2() throws -> ReturnType {}
// Fonction qui ne gère pas les erreurs
func nonthrowFunc() {}

Vous pouvez imaginer que lorsque l'on tente de démarrer une voiture, celle-ci pourrait ne pas démarrer si elle n'a pas d'essence ou si son moteur est endommagé. Voici comment modéliser cela :

struct Car {
    var fuelLevel: Int
    var engineRunnable: Bool
    var replaceOil: Bool
}

func start(car: Car) throws {
    if !car.engineRunnable {
        throw CarError.brokenEngine
    }
    if car.fuelLevel <= 0 {
        throw CarError.noFuel
    }
    if car.replaceOil {
        throw CarError.check(fluid: "Oil")
    }
}

Appel de fonctions émettant des erreurs

Lorsqu'une fonction appelle une autre fonction qui émet une erreur, elle doit gérer cette erreur soit avec un bloc do-catch, soit déclarer qu'elle émet également des erreurs. On utilise le mot-clé try lors de l'appel d'une fonction émettant une erreur :

func tryError() throws {
    // Appel d'une fonction et assignation de la valeur retournée
    let x = try throwingFuncWithReturningValue()
    // Appel d'une fonction sans valeur de retour
    try throwingFuncWithoutReturn()
}

Gestion des erreurs

Une instruction do-catch permet de capturer et de gérer les erreurs provenant des fonctions émettrices à l'intérieur de la fonction appelante. Voici un exemple :

func handleErrors() {
    do {
        let x = try throwingFuncWithReturningValue()
        try throwingFuncWithoutReturn()
    } catch SomeError.condition {
        // Gérer une condition spécifique
    } catch {
        // Gestion d'une erreur générique
    }
}
` 
Par exemple, voici l'implémentation d'un `do-catch` dans une fonction pour conduire une voiture :

func drive(car: Car) { do { try start(car: car) } catch CarError.noFuel { print("Impossible de démarrer le moteur ! Pas d'essence !") } catch CarError.brokenEngine { print("Le moteur est endommagé") } catch CarError.check(let fluid) { print("Vérifiez le (fluid)") } catch { print("Erreur inattendue") } }