Programmation asynchrone en Swift : guide complet avec exemples

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction à la programmation asynchrone en Swift

Les applications modernes mobiles et de bureau en Swift (iOS/macOS) nécessitent de plus en plus d'effectuer des opérations de longue durée — chargement de données depuis le réseau, travail avec des fichiers, traitement d'images — sans bloquer l'interface utilisateur. Jusqu'à récemment, les développeurs utilisaient des closures (gestionnaires d'achèvement) et Grand Central Dispatch (GCD), ce qui menait au soi-disant "callback hell" et compliquait la lisibilité du code. Avec la sortie de Swift 5.5, Apple a introduit un modèle de programmation asynchrone fondamentalement nouveau basé sur les mots-clés async et await, ainsi que les acteurs et les structures Task. Dans ce guide, nous allons décomposer tous les concepts clés avec des exemples pratiques.



1. Les bases de async/await en Swift

Le mot-clé async indique qu'une fonction ou une méthode peut suspendre son exécution pour attendre le résultat d'une opération asynchrone. Un appel à une telle fonction est marqué par le mot await. Cela permet d'écrire du code asynchrone aussi linéairement que du code synchrone.



// Déclaration d'une fonction asynchronefunc fetchUserData(from url: URL) async throws -> Data {    let (data, _) = try await URLSession.shared.data(from: url)    return data}

// Utilisation dans un contexte de tâcheTask { do { let url = URL(string: "https://api.example.com/user")! let userData = try await fetchUserData(from: url) print("Données reçues : \\(userData.count) octets") } catch { print("Erreur de chargement : \\(error.localizedDescription)") }}


Remarque : l'appel await suspend la tâche en cours mais ne bloque pas le thread. Le système change lui-même de contexte lorsque le résultat est prêt, rendant le code efficace et sûr.



2. Acteurs — gestion sécurisée de l'état

L'asynchronisme introduit le problème des conditions de concurrence (data races). Pour le résoudre, Swift a introduit les acteurs. Un acteur est un type de référence qui isole son état et garantit qu'une seule tâche peut accéder à ses propriétés mutables à un moment donné.



actor Counter {    private var value = 0        func increment() {        value += 1    }        func getValue() -> Int {        return value    }}

// Utilisation d'un acteurlet counter = Counter()

Task { await counter.increment() let currentValue = await counter.getValue() print("Valeur actuelle : \\(currentValue)")}


Le mot-clé actor rend automatiquement toutes les méthodes et propriétés (sauf immuables) asynchrones pour un accès externe. Cela permet d'éviter les verrous et les blocages typiques de la gestion manuelle des verrous (NSLock, DispatchSemaphore).



3. TaskGroup et exécution parallèle des tâches

Lorsque vous devez exécuter plusieurs opérations asynchrones indépendantes en parallèle, utilisez TaskGroup. Il s'agit d'une structure qui permet de lancer des tâches enfants et de collecter leurs résultats.



func fetchMultipleUsers(ids: [Int]) async throws -> [User] {    try await withThrowingTaskGroup(of: User.self) { group in        var users: [User] = []                for id in ids {            group.addTask {                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.0)            }        }                for try await user in group {            users.append(user)        }        return users    }}

// UtilisationTask { let users = try? await fetchMultipleUsers(ids: [1, 2, 3, 4, 5]) print("Utilisateurs chargés : \\(users?.count ?? 0)")}


La méthode withThrowi

Blogs

Book Recommendations