Revenir

Entre ton email pour recevoir le guide complet pour apprendre Swift peu importe ton niveau

Les méthodes pour que votre code Swift ne plante plus jamais

Tous les programmes ont des situations où ils peuvent créer des erreurs.

C’est presque inévitable mais c’est normal car on ne peut pas prévoir le comportement de l’utilisateur de notre programme.

Plutôt que d’empêcher toutes les erreurs d’exister, il faut apprendre à les gérer.

Il faut apprendre à les gérer pour ne pas faire planter le programme et faire partir l’utilisateur.

Souvent, on oublie de bien gérer les erreurs car on se dit que ça n’arrivera pas ou que ça ne peut pas arriver.

Mais on ne peut jamais en être sûr, c’est pourquoi il faut être rigoureux avec ça.

Guard let vs If let

Les optionnels sont la première source d’erreur en Swift.

Quand on les déballe pour accéeder à leur valeur, on ne sait jamais ce qu’il y aura à l’avance.

À moins de l’avoir spécifié vous-même avant.

Voici comment les déballer en sécurité avec guard let:

guard let url = URL(string: "https://medium.com") else { return }

Utiliser guard let sert à créer une variable qui sera accessible dans le scopre de la fonction qui contient cette déclaration.

Ça sert aussi à faire arrêter la fonction si jamais on n’a pas la valeur qu’on veut.

Si jamais, dans une fonction, vous ne voulez pas arrêter la fonction si vous n’avez pas la valeur que vous voulez ou si vous faites une chose différente en fonction de si elle est là ou non, alors vous pouvez utiliser if let:

if let data = rawData as? [String: [String: String]] {
    print("converted data successfully")
}
else if let data = rawData as? [String: [String]] {
    print("second attempt worked")
}
else {
    print("Error")
}

Je vous recommende d’essayer d’utiliser au maximum guard let car votre code sera plus propre.

Ça évite d’avoir beaucoup de if let imbriqués si vous avez plusieurs optionnels à gérer ce qui ne serait pas très lisible.

Try … catch

Parfois on doit également gérer des cas dans lesquels on va retourner une sous classe de l’objet Error

Les fonctions qui sont susceptibles de retourner des erreurs sont marquées sont définies comme ça:

func canThrowErrors() throws -> String

Si une fonction est déclarée comme ça, vous devez l’appeler dans un bloc try ... catch:

do {
    try canThrowErrors()
}
catch ErrorSubclass {
    print(error)
}

Dans ce code, si la fonction retourne une erreur de type ErrorSubclass alors on éxecute le code dans le bloc catch.

Voici les différents patternes que vous pouvez utiliser dans un catch:

do {
    try expression
    statements
} catch ErrorType {
    statements
} catch ErrorType where condition {
    statements
} catch {
    // catch any error
    statements
}

Vous pouvez vous-mêmes créer vos propres erreurs en fonction de ce que fait votre code.

Et c’est même fortement recommendé pour avoir un total contrôle sur toutes les situations possibles dans votre code.

Voici un exemple:

enum EcommerceError: Error {
    case InvalidProduct
    case NotAvailable
    case NotEnoughMoney(price: Int)
    case InvalidAddress
    case InvalidPaymentInformation
}

Ce code va nous créer un nouveau type d’erreur qui est EcommerceError.

Voici comment on peut l’utiliser:

func buyItem(items: [Int: Int], item: [String: Int], address: String, paymentInfo: [String: Int]) throws {
    guard items.contains(item["number"]) else { throw EcommerceError.InvalidProduct }
    guard items[item["number"]] > 0 else { throw EcommerceError.NotAvailable }
    guard paymentInfo["money"] >= item["price"] else { throw EcommerceError.NotEnoughMoney(price: item["price"]) }
    guard address.isValidAddress() else { throw EcommerceError.InvalidAddress }
    guard isPaymentInfoValid(info: paymentInfo) else { throw EcommerceError.InvalidPaymentInformation }

    // run code to buy item 
}

func isPaymentInfoValid(info: [String: Int]) -> Bool {
    // check if info is correct
    return true
}

extension String {
    func isValidAddress() -> Bool {
        // check if string is address
        return true
    }
}

Dans ce code on vérifie chaque information sur le produit et son acheteur et en fonction de l’erreur possible on retourne un certain type d’erreur.

Voici comment on utiliserait la fonction buyItems:

let items = [100: 2, 430: 5, 1238: 19]
let item = ["number": 100, "price": 50]
let address = "valid address"
let paymentInfo = ["card": 4242424242424242, "month": 2, "year": 21, "ccv": 100, "money": 100]

do {
    try buyItems(items: items, item: item, address: address, paymentInfo: paymentInfo)
}
catch EcommerceError.InvalidProduct {
    print("Invalid Product.")
}
catch EcommerceError.NotAvailable {
    print("Out of Stock.")
}
catch EcommerceError.NotEnoughMoney(let price) {
    print("Insufficient money. The price is: \(price)")
}
catch EcommerceError.InvalidAddress {
    print("Please enter a valid address")
}
catch EcommerceError.InvalidPaymentInformation {
    print("Could not proceed payment due to invalid payment information")
}
catch {
    print("Unexpected error: \(error).")
}

Dans ce code on affiche une erreur dufférente en fonction de ce qui n’a pas marché dans la fonction buyItems et on utilise le type d’erreur que l’on a créé afin d’avertir l’utilisateur de ce qui n’a pas marché.

Conclusion

Avec cet article, vous avez tout ce qu’il faut pour gérer au mieux les erreurs de votre code.

Ça vous sera extrêmement utile pour éviter de faire planter l’application que vous créez et donc de oerdre des utilisateurs.

Merci d’avoir lu cet article !