RxSwift est une bibliothèque de programmation réactive pour iOS qui implémente le modèle Observable et des opérateurs fonctionnels pour travailler avec des flux de données asynchrones. Elle porte les concepts de ReactiveX (Rx) vers Swift, fournissant une API unifiée pour gérer les événements de l'UI, les requêtes réseau, les bases de données et les minuteurs. Selon ReactiveX, 2025, la bibliothèque est utilisée dans plus de 60 000 projets sur GitHub et reste la norme de programmation réactive pour Swift jusqu'à l'avènement du Combine natif. RxSwift remplace les délégués, les closures et les notifications par une chaîne unique de traitement d'événements.
Points essentiels
RxSwift est le port Swift de la bibliothèque ReactiveX (Rx) créée par Microsoft pour .NET en 2012. L'idée centrale de Rx est de représenter toute source de données asynchrone comme une séquence Observable à laquelle des opérateurs fonctionnels peuvent être appliqués. Dans le développement iOS, RxSwift est utilisé pour lier les événements de l'UI (touches de boutons, saisie de texte, gestes) à la logique de l'application sans délégués explicites ni target-action.
La bibliothèque se compose de trois modules : RxSwift (noyau — Observable, Operator, Scheduler), RxCocoa (intégration UIKit — extensions rx pour UIButton, UITextField, UITableView) et RxRelay (Subject sans événements terminaux). Cette séparation permet d'utiliser le noyau dans du Swift côté serveur et dans les tests, en connectant l'encapsulation UI uniquement pour les applications iOS.
Selon l'enquête Stack Overflow, 2025, RxSwift fait partie des 5 bibliothèques tierces les plus utilisées pour iOS. La principale raison de sa popularité est le traitement uniforme de tous les modèles asynchrones : requêtes réseau via URLSession, animations via UIViewPropertyAnimator, notifications via NotificationCenter et délégués via DelegateProxy — tout se résume à un Observable avec un cycle de vie prévisible.
La programmation réactive est un paradigme dans lequel le programme réagit aux changements de données plutôt que de les interroger. Au lieu d'écrire « obtenir des données → traiter → mettre à jour l'UI », le développeur décrit une chaîne de transformations : « quand les données changent, appliquer un filtre, puis map, puis mettre à jour l'UI ». RxSwift implémente ce paradigme via des chaînes Observable avec exécution paresseuse — rien ne se produit jusqu'à ce qu'un abonné apparaisse.
Observable est le type fondamental de RxSwift représentant une séquence d'événements dans le temps. Observable peut envoyer trois types d'événements : next (nouvelle valeur), error (erreur terminant le flux) et completed (achèvement réussi). Il existe des Observable finis (se terminent après l'envoi de toutes les valeurs) et des Observable infinis (par exemple, les événements de l'UI — ne se terminent jamais).
Le cycle de vie d'un Observable comprend trois étapes : création (create, just, from), transformation (opérateurs map, filter, flatMap) et abonnement (subscribe). Sans abonnement, Observable n'effectue aucune action — c'est une séquence paresseuse. Après l'abonnement, Observable commence à envoyer des événements à l'abonné jusqu'à ce qu'il se termine ou que l'abonné annule l'abonnement via Disposable.
import RxSwift
// Créer Observable à partir d'un tableau
let numbers = Observable.from([1, 2, 3, 4, 5])
// Transformation via les opérateurs
let squared = numbers
.filter { $0 % 2 == 0 }
.map { $0 * $0 }
// Abonnement avec gestion d'événements
let disposable = squared
.subscribe(onNext: { print($0) },
onError: { print("Error: \($0)") },
onCompleted: { print("Done") })
Subject est un type qui est à la fois un Observable (auquel on peut s'abonner) et un Observer (auquel on peut envoyer des événements). RxSwift fournit quatre types de Subject : PublishSubject (uniquement les nouveaux événements), BehaviorSubject (avec une valeur initiale), ReplaySubject (met en mémoire tampon les N derniers événements) et AsyncSubject (seulement la dernière valeur avant l'achèvement). Subject est utile pour intégrer du code impératif (closures, délégués) dans une chaîne réactive.
Disposable est un jeton d'annulation d'abonnement. Lorsque l'abonné ne souhaite plus recevoir d'événements, il appelle disposable.dispose(). En pratique, on utilise DisposeBag : une collection de Disposable qui annule automatiquement tous les abonnements lors de la désinitialisation du propriétaire (par exemple, UIViewController). Cela évite les fuites de mémoire inévitables avec la gestion manuelle des abonnements.
| Type de Subject | Valeur initiale | Réémet à l'abonné | Cas d'utilisation |
|---|---|---|---|
| PublishSubject | Non | Nouveaux événements uniquement | Événements UI, notifications rares |
| BehaviorSubject | Oui | Dernier + nouveaux | État, flux de données |
| ReplaySubject | Non | Tampon N + nouveaux | Mise en cache de l'historique |
| AsyncSubject | Non | Seulement le dernier | Tâches computationnelles |
| PublishRelay | Non | Nouveaux uniquement | Sans error/completed |
Les opérateurs dans RxSwift sont des fonctions qui prennent un Observable et retournent un autre Observable, transformant le flux de données. En combinant des opérateurs, le développeur construit des chaînes de traitement déclaratives sans variables intermédiaires ni conditions de concurrence. Tous les opérateurs sont paresseux : la chaîne est construite lors de la description et exécutée lors de l'abonnement.
Les opérateurs de transformation modifient chaque événement dans le flux. map applique une fonction à chaque élément, flatMap déplie l'Observable de chaque élément en un seul flux plat, scan accumule les résultats intermédiaires (similaire à reduce mais en émettant chaque étape). buffer regroupe les éléments par temps ou quantité, window divise le flux en Observable imbriqués par fenêtres.
// Exemple de chaîne d'opérateurs : recherche avec debounce
searchTextField.rx.text
.orEmpty
.debounce(.milliseconds(300), scheduler: MainScheduler.instance)
.distinctUntilChanged()
.flatMapLatest { query -> Observable<[String]> in
return apiService.search(query)
}
.bind(to: tableView.rx.items(cellIdentifier: "Cell")) { _, item, cell in
cell.textLabel?.text = item
}
.disposed(by: disposeBag)
Les opérateurs de filtrage ne laissent passer que les événements qui satisfont une condition. filter filtre par prédicat, distinctUntilChanged ne laisse passer que les valeurs différentes de la précédente, take et takeWhile limitent le nombre d'événements. skip et skipWhile sautent les N premiers événements ou les événements jusqu'à ce qu'une condition soit remplie. Pour la gestion des erreurs, on utilise catchError (intercepter et substituer) et retry (réessayer la séquence en cas d'erreur).
Les opérateurs de combinaison combinent plusieurs Observables en un seul. combineLatest fusionne les dernières valeurs de plusieurs flux en un tuple, zip associe les éléments avec les mêmes indices, merge combine plusieurs flux en un dans l'ordre d'arrivée des événements. withLatestFrom combine un événement du flux principal avec la dernière valeur d'un autre flux — utile pour les événements UI avec état courant.
| Catégorie | Opérateur | Description |
|---|---|---|
| Transformation | map | Transforme chaque valeur via une fonction |
| Transformation | flatMap | Déplie les Observable imbriqués en un flux plat |
| Filtrage | filter | Laisse passer les valeurs selon un prédicat |
| Filtrage | distinctUntilChanged | Laisse passer uniquement les valeurs modifiées |
| Combinaison | combineLatest | Combine les dernières valeurs de 2+ flux |
| Combinaison | zip | Associe les éléments par index |
| Contrôle | debounce | Retarde les événements jusqu'à une pause dans le flux |
| Contrôle | take | Prend les N premiers événements et termine le flux |
Scheduler dans RxSwift est une abstraction sur le thread d'exécution (ou la file d'attente). Scheduler détermine sur quel thread la création d'événements, la transformation et l'abonnement sont exécutés. Contrairement à GCD, où le développeur spécifie explicitement DispatchQueue, RxSwift utilise deux paramètres : subscribeOn (sur quel thread l'Observable s'exécute) et observeOn (sur quel thread l'abonné est appelé).
MainScheduler exécute le code sur le thread principal — obligatoire pour les mises à jour UIKit (toutes les modifications de l'UI doivent avoir lieu sur le thread principal). SerialDispatchQueueScheduler encapsule une file d'attente GCD série, ConcurrentDispatchQueueScheduler une file d'attente concurrente. Pour les tâches d'arrière-plan, on utilise ConcurrentDispatchQueueScheduler avec qos : .background ou .utility.
// Modèle typique : travail en arrière-plan + UI sur main
apiService.fetchData()
.subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
.observeOn(MainScheduler.instance)
.subscribe(onNext: { data in
self.tableView.reloadData()
self.loadingIndicator.stopAnimating()
})
.disposed(by: disposeBag)
L'utilisation correcte de Scheduler empêche le blocage de l'UI lors des requêtes réseau et des calculs lourds. subscribeOn affecte tout l'amont (tous les opérateurs avant observeOn s'exécutent sur le planificateur spécifié). observeOn bascule l'aval — tous les opérateurs après observeOn s'exécutent sur le planificateur spécifié. Une chaîne peut avoir plusieurs observeOn pour basculer entre les threads à différentes étapes de transformation.
SerialDispatchQueueScheduler garantit un traitement séquentiel des événements, ce qui est important pour la sécurité des threads des ressources partagées. Pour les opérations à forte charge (traitement d'images, analyse JSON), utilisez ConcurrentDispatchQueueScheduler — RxSwift préservera l'ordre des événements au sein d'un Observable, mais différents Observables peuvent être traités en parallèle.
RxSwift dans les projets iOS est le plus souvent utilisé pour lier l'UI aux données via des chaînes réactives. RxCocoa fournit des extensions rx pour tous les composants UIKit standards : rx.tap pour UIButton, rx.text pour UITextField, rx.selectedRow pour UIPickerView. Cela permet d'abandonner @IBAction et les délégués, en les remplaçant par des abonnements déclaratifs.
MVVM (Model-View-ViewModel) est un modèle architectural dans lequel ViewModel gère l'état et la logique métier, et View s'abonne aux propriétés réactives de ViewModel. RxSwift s'intègre parfaitement avec MVVM : ViewModel publie Observable ou Driver pour les données, View s'y abonne via bind. ViewModel n'a pas de référence à View — il retourne des Observable que View consomme.
class LoginViewModel {
let email = BehaviorRelay<String>(value: "")
let password = BehaviorRelay<String>(value: "")
var isFormValid: Observable<Bool> {
return Observable
.combineLatest(email, password) {
!$0.isEmpty && $0.contains("@") && $1.count >= 6
}
}
}
// Dans ViewController :
viewModel.isFormValid
.bind(to: loginButton.rx.isEnabled)
.disposed(by: disposeBag)
Les requêtes réseau sont le deuxième cas d'utilisation le plus courant de RxSwift. URLSession.rx.response encapsule une requête HTTP dans un Observable qui retourne (response, data) en cas de succès ou error en cas d'échec. En combinaison avec Codable et l'opérateur map, on obtient une couche API réactive compacte : Observable<MyModel> sans callbacks ni gestion d'erreurs dans chaque méthode. En cas d'erreur réseau, l'opérateur retry(3) réessaie automatiquement la requête trois fois avec un backoff exponentiel.
Combine est le framework natif d'Apple présenté dans iOS 13. Il résout les mêmes tâches que RxSwift : travailler avec des événements asynchrones via Publisher, Subscriber et des opérateurs. Cependant, Combine présente des différences clés : typage strict des erreurs via le type Failure, prise en charge intégrée de Swift Concurrency (async/await) et intégration avec SwiftUI via @Published et ObservableObject.
RxSwift l'emporte en matière de rétrocompatibilité — il supporte iOS 8+, alors que Combine nécessite iOS 13+. RxSwift dispose d'un écosystème plus riche d'extensions tierces (RxDataSources, RxGesture, RxAnimated) et d'une documentation détaillée des opérateurs. Pour les projets prenant en charge les anciennes versions d'iOS, RxSwift reste le seul choix.
Pour les nouveaux projets avec iOS 13+, Apple recommande Combine. Il est étroitement intégré à SwiftUI, a une taille binaire plus petite et un support officiel. Cependant, la migration du code RxSwift existant vers Combine nécessite la réécriture de tous les Observable → Publisher, et l'écosystème RxCocoa n'a pas d'équivalent complet dans Combine — UIKit n'a pas de Publisher natif pour tous les composants de l'UI.
| Caractéristique | RxSwift | Combine |
|---|---|---|
| iOS minimum | iOS 8+ | iOS 13+ |
| Type d'erreur | Error (quelconque) | Generic Failure |
| Extensions UI | RxCocoa (UIKit, AppKit) | @Published (SwiftUI) |
| Opérateurs | 400+ opérateurs | ~100 opérateurs |
| Swift Concurrency | Via pont | Support natif |
| Statut | Tierce | Apple officiel |
Foire aux questions
Observable est une source d'événements avec exécution paresseuse. Subject est à la fois un Observable et un Observer — vous pouvez vous y abonner et lui envoyer manuellement de nouveaux événements. Subject est utile pour intégrer du code impératif dans les chaînes réactives.
RxSwift est choisi lorsqu'un support iOS 11-12 est nécessaire, qu'une base de code RxSwift existante est présente ou qu'un écosystème riche d'opérateurs est requis (400+ contre ~100 dans Combine). Pour les nouveaux projets sur iOS 13+, Combine est préféré.
DisposeBag est une collection de jetons Disposable qui annule automatiquement tous les abonnements lors de la désinitialisation du propriétaire. Sans DisposeBag, l'abonnement crée une référence forte vers la closure, entraînant des fuites de mémoire lors de la destruction du UIViewController.
Utilisez catchError pour remplacer une erreur par une valeur par défaut, retry pour réessayer l'exécution d'Observable, materialize pour transformer l'erreur en événement. Dans la couche UI, Driver et Signal ne transmettent pas d'erreurs — elles sont traitées en interne.
Driver est un type spécial d'Observable qui garantit l'exécution sur MainScheduler, l'absence d'erreurs et le partage de ressources. Driver garantit que les mises à jour de l'UI se produisent sur le thread principal. Observable n'offre pas de telles garanties — observeOn est nécessaire.
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