Skip to main content

Alessandros's Blog - Build with freedom. Share with purpose

15 Juillet 2025 - Gestion des données manquantes avec les Optionals Swift

Jour 37 de formation et 14ème jour des 100 Days of SwiftUI ! Aujourd’hui, nous entrons dans l’un des concepts les plus importants et parfois déroutants de Swift : les Optionals. Paul Hudson le dit lui-même : “Optionals and Closures are the most important and difficult to understand in Swift”.

# Comprendre les Optionals : la boîte de Schrödinger du code

Les Optionals en Swift, c’est comme une boîte : quelque chose peut être dedans, ou pas. Cette métaphore m’aide vraiment à visualiser le concept. Contrairement à d’autres langages où une variable peut parfois contenir quelque chose de inattendu, Swift nous force à être explicites sur ce qui peut être absent.

## Pourquoi les Optionals existent-ils ?

Imaginons qu’on cherche l’opposé de “Peach” dans notre dictionnaire de personnages Mario :

let opposites = ["Mario": "Wario", "Luigi": "Waluigi"]
let peachOpposite = opposites["Peach"] // Que se passe-t-il ?

Swift ne peut pas deviner ce qu’on veut faire si “Peach” n’existe pas. Plutôt que de planter ou de retourner une valeur par défaut arbitraire, il retourne un Optional - une boîte qui peut contenir une valeur ou être vide.

# Les différentes façons de “déballer” un Optional

## 1. If Let : la méthode sécurisée

La technique if let permet de vérifier s’il y a quelque chose dans la boîte avant de l’utiliser :

if let peachOpposite = opposites["Peach"] {
    print(peachOpposite)
} else {
    print("Nothing in Array")
}

Ce qui me plaît avec cette approche, c’est qu’elle crée une version temporaire et non-optionnelle de notre variable uniquement dans le scope du if. Pas de risque d’erreur !

## 2. Guard : sortir tôt en cas de problème

Les guards inversent la logique - ils s’occupent du cas d’erreur en premier :

func printSquare(of number: Int?) {
    guard let number = number else {
        print("Missing Input")
        return
    }
    print("\(number) x \(number) is \(number * number)")
}

Cette approche me semble plus naturelle pour les fonctions : on traite d’abord les cas problématiques, puis on se concentre sur la logique principale.

## 3. Nil Coalescing : fournir une valeur par défaut

L’opérateur ?? (nil coalescing) est génial quand on veut simplement une valeur de secours :

let favorite = tvShow.randomElement() ?? "None"
let userInput = Int(input) ?? 0

C’est ma technique préférée quand je veux que l’application continue à fonctionner même si une donnée manque.

# Optional Chaining : enchaîner les “peut-être”

L’Optional Chaining permet d’enchaîner plusieurs opérations qui pourraient échouer :

let chosen = names.randomElement()?.uppercased() ?? "No One"

Si randomElement() retourne nil, toute la chaîne s’arrête et retourne nil. Sinon, on continue avec uppercased(). C’est élégant et sûr !

# Try? : quand les erreurs deviennent des Optionals

Avec try?, on peut transformer une fonction qui lance des erreurs en Optional :

if let user = try? getUser(id: 23) {
    print("User: \(user)")
}

Cette approche est parfaite quand le détail de l’erreur ne nous intéresse pas - on veut juste savoir si ça a marché ou pas.

# Exercices pratiques réalisés

## Challenge du jour : fonction en une ligne

Le défi était d’écrire une fonction qui accepte un array optionnel d’entiers et retourne un élément aléatoire, ou un nombre entre 1 et 100 si l’array est vide ou nil :

let arrayOneLine = { (array: [Int]?) -> Int in 
    array?.randomElement() ?? Int.random(in: 1...100) 
}

Voir cette solution fonctionner m’a donné l’impression de résoudre un puzzle - combiner optional chaining et nil coalescing en une ligne élégante.

## Exercices d’approfondissement

J’ai ensuite travaillé sur plusieurs exercices pour maîtriser les différentes techniques :

  • Comptage de caractères sécurisé : gérer les chaînes nil
  • Extraction du premier élément : avec optional chaining
  • Calculs avec valeurs par défaut : utiliser nil coalescing pour les opérations
  • Calcul de moyenne robuste : combiner guard et vérifications
  • Conversion conditionnelle : transformer des mots en nombres avec gestion d’erreur

## Leçon apprise avec les Guards

Une découverte importante : on peut combiner plusieurs conditions dans un guard avec des virgules :

guard let number = number, let convertedNumber = convertDict[number] else {
    return -1
}

Cette syntaxe est plus propre que d’imbriquer plusieurs guards.


À demain pour le dernier jour théorique des 100 Days of SwiftUI !