Do-Catch est une construction du langage Swift pour la gestion d’erreurs qui intercepte les exceptions levées via throw et exécute le bloc de code correspondant. Contrairement au try-catch traditionnel dans d’autres langages, Swift exige un marquage explicite des fonctions qui peuvent lever une erreur avec le modificateur throws. Selon Swift.org, 2026, Do-Catch est le mécanisme principal de gestion d’erreurs en Swift, offrant la sécurité de types.
Points clés
Do-Catch est une construction en Swift consistant en un bloc do, à l’intérieur duquel du code capable de lever une erreur est exécuté, et un ou plusieurs blocs catch qui traitent cette erreur. Le bloc do contient des appels à des fonctions throwing marquées avec try, et les blocs catch correspondent à l’erreur par type.
Swift implémente un modèle de gestion structurée des erreurs, différent des exceptions en Objective-C. Ici, une erreur n’est pas une exception avec déroulement de pile, mais une valeur conforme au protocole Error. Lever une erreur via throw transfère le contrôle au bloc catch le plus proche sans la surcharge du déroulement de pile.
Une caractéristique clé de Swift est la gestion explicite. Le compilateur ne permet pas d’appeler une fonction throwing sans try, do-catch ou un mécanisme alternatif (try?, try!). Cela élimine les situations où une erreur passe inaperçue.
Au cœur de la gestion d’erreurs en Swift se trouve le protocole Error. Tout type conforme à ce protocole peut être levé via throw. Les erreurs sont généralement définies comme une enum conforme à Error.
Error est un protocole vide (marqueur). Il ne nécessite pas d’implémentation de méthodes, seulement la conformité. Le compilateur Swift utilise Error pour la vérification statique : une fonction avec throws ne peut lever qu’une valeur conforme à Error.
Une fonction marquée avec throws doit être appelée avec try. Si un throw se produit à l’intérieur de cette fonction, le contrôle est transféré au do-catch appelant. Si l’erreur n’est traitée nulle part dans la chaîne d’appels, elle se propage au niveau supérieur.
enum FileError: Error {
case notFound
case permissionDenied
case corrupted(String)
}
func readFile(path: String) throws -> String {
guard FileManager.default.fileExists(atPath: path) else {
throw FileError.notFound
}
return try String(contentsOfFile: path)
}
rethrows est un modificateur pour les fonctions qui acceptent une closure throwing comme paramètre. Si la closure passée ne lève pas d’erreur, la fonction rethrows peut être appelée sans try. Cela permet d’écrire des fonctions génériques d’ordre supérieur compatibles avec les closures throwing et non-throwing.
Swift prend en charge plusieurs blocs catch avec correspondance d’erreurs par type. Cela ressemble à when en Kotlin ou un switch par type : le premier catch correspondant est exécuté, les autres sont ignorés.
Chaque bloc catch peut contenir un motif correspondant à un type d’erreur spécifique. Swift vérifie les blocs dans l’ordre, donc les types plus spécifiques doivent venir avant les types généraux. Si aucun motif ne correspond, le bloc catch sans motif est exécuté.
La sécurité de types de Do-Catch permet de traiter chaque erreur séparément ou de combiner plusieurs types dans un bloc via une correspondance de motifs séparée par des virgules. Cela élimine les chaînes if-else lourdes typiques d’Objective-C, où l’analyse d’erreurs se faisait via des codes de retour ou NSError avec vérification de domaine et de code.
Swift prend également en charge catch where — correspondance avec une condition supplémentaire. Par exemple, vous pouvez filtrer les erreurs par un code ou un texte spécifique : catch URLError where error.code == .notConnectedToInternet. Cela réduit le nombre de blocs catch tout en maintenant la précision.
Pour déboguer les fonctions throwing, Swift fournit une distinction entre erreurs et exceptions. Une erreur Swift est une valeur de retour qui ne nécessite pas de déroulement de pile. Les exceptions Objective-C (@try/@catch) fonctionnent au niveau de l’exécution et ne sont utilisées que pour les échecs fatals. Do-Catch traite les erreurs, pas les exceptions, ce qui le rend prévisible et performant.
Lors du développement de bibliothèques et SDK, il est important de se rappeler que les fonctions throwing font partie du contrat public. Le type d’erreur n’est pas spécifié dans la signature, donc documentez les erreurs qu’une fonction peut lever dans les commentaires ou via des enum de type Result. Cela aide les utilisateurs d’API à écrire des blocs catch corrects sans avoir à consulter l’implémentation.
Dans le contexte de la programmation asynchrone, Do-Catch avec async/await résout le problème de l’enfer des callbacks. Auparavant en Swift, la gestion d’erreurs dans le code asynchrone nécessitait des closures imbriquées avec vérification de Error? dans les gestionnaires d’achèvement. Avec async/await et Do-Catch, le code asynchrone throwing ressemble à du code synchrone, simplifiant la lecture et la maintenance de chaînes de requêtes complexes avec gestion d’erreurs à chaque étape.
do {
let content = try readFile(path: "/data/config.json")
process(content)
} catch FileError.notFound {
createDefaultConfig()
} catch FileError.permissionDenied {
requestAccess()
} catch FileError.corrupted(let detail) {
logCorruption(detail)
} catch {
print("Erreur inconnue : \(error)")
}
Swift offre trois façons d’appeler les fonctions throwing : try, try? et try!. Chaque option résout une tâche spécifique et a ses limites.
try est utilisé dans un bloc do, et l’erreur est traitée dans catch. C’est la façon principale d’appeler les fonctions throwing. Le compilateur exige que try soit dans un contexte où l’erreur peut être interceptée.
try? convertit le résultat d’une fonction throwing en Optional. Si la fonction lève une erreur, try? retourne nil, sinon retourne un Optional avec la valeur réussie. Utile pour les appels où l’erreur peut être ignorée mais un indicateur de succès est nécessaire.
try! supprime la gestion d’erreurs. Si la fonction throwing lève une erreur, l’application se termine avec une erreur d’exécution. Utilisez try! seulement lorsque vous êtes absolument sûr que l’erreur est impossible — par exemple, lors du chargement d’une ressource intégrée.
// try? — nous ignorons l’erreur, obtenons nil en cas d’échec
if let data = try? Data(contentsOf: url) {
processData(data)
}
// try! — seulement si l’erreur est garantie impossible
let bundled = try! String(contentsOfFile: "Assets/default.txt")
// try — option standard dans do-catch
do {
let result = try performNetworkRequest()
updateUI(result)
} catch {
showError(error)
}
Do-Catch est activement utilisé dans le développement iOS pour travailler avec les API système. Considérons des scénarios typiques : travail avec le système de fichiers, Core Data et les requêtes réseau.
De nombreuses méthodes de FileManager sont throwing. Do-Catch permet de traiter correctement l’absence de fichier, l’occupation de ressource ou les permissions insuffisantes.
L’analyse JSON via JSONDecoder est une opération throwing. Do-Catch intercepte les erreurs de décodage et les échecs réseau séparément, fournissant à l’utilisateur un message d’erreur précis.
struct User: Codable {
let id: Int
let name: String
}
func fetchUser(id: Int) async throws -> User {
let url = URL(string: "https://api.example.com/users/\(id)")!
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode(User.self, from: data)
}
// Appel avec traitement
do {
let user = try await fetchUser(id: 42)
showUser(user)
} catch let error as URLError {
showNetworkAlert(error)
} catch let error as DecodingError {
showParseError(error)
} catch {
showGenericError(error)
}
Les développeurs, en particulier ceux venant d’autres langages, commettent souvent des erreurs caractéristiques lors de l’utilisation de Do-Catch. Examinons les plus courantes.
Foire aux questions
En Swift, une erreur est une valeur conforme au protocole Error, pas une exception avec déroulement de pile. Les fonctions throwing doivent être explicitement marquées avec throws, et le compilateur exige try lors de l’appel — cela élimine les erreurs non traitées à la compilation.
Oui, les fonctions async peuvent aussi être throws, et do-catch fonctionne avec elles. Appeler une fonction async throwing nécessite try await dans un bloc do. C’est la façon standard de gérer les erreurs dans le code asynchrone Swift.
Il existe des alternatives : try? convertit l’erreur en nil, try! provoque un crash en cas d’erreur, et rethrows permet de propager une erreur depuis une closure. Do-catch reste la façon principale de gestion explicite.
Swift ne type pas les erreurs levées — toute fonction throwing peut lever tout type conforme à Error. Séparez le traitement par correspondance dans catch par types d’erreurs spécifiques.
Oui, c’est une bonne pratique. Définissez AppError comme une enum conforme à Error et convertissez les erreurs système en erreurs de domaine. Cela unifie le traitement et isole la couche applicative des détails système.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi