Programmation réactive en Swift (iOS/macOS) : Combine et RxSwift
La programmation réactive est un paradigme basé sur le travail avec des flux de données asynchrones et la propagation des changements. Dans l'écosystème Apple pour iOS et macOS, les principaux outils sont le framework natif Combine (depuis iOS 13/macOS 10.15) et la bibliothèque tierce RxSwift. Tous deux permettent d'écrire un code déclaratif, concis et facilement testable, libérant le développeur de « l'enfer des callbacks » et de la gestion complexe de l'état.
Concepts de base
- Publisher (Éditeur) — source de données qui peut envoyer des valeurs, une terminaison ou une erreur.
- Subscriber (Abonné) — reçoit les données du Publisher et y réagit.
- Operator (Opérateur) — fonction de transformation du flux (map, filter, combineLatest, debounce, etc.).
- Subject — hybride qui peut à la fois recevoir et envoyer des événements (PassthroughSubject, CurrentValueSubject).
- Scheduler (Planificateur) — détermine sur quel thread le code s'exécute.
Combine : le framework natif d'Apple
Combine est intégré à Foundation et fonctionne avec Publisher et Subscriber. Exemple d'utilisation pour le traitement d'un champ de texte :
import Combineimport UIKit
class ViewController: UIViewController { @IBOutlet weak var textField: UITextField! @IBOutlet weak var label: UILabel! private var cancellables = Set<AnyCancellable>()
override func viewDidLoad() { super.viewDidLoad() // Création d'un Publisher à partir de NotificationCenter let publisher = NotificationCenter.default .publisher(for: UITextField.textDidChangeNotification, object: textField) .compactMap { ($0.object as? UITextField)?.text } .debounce(for: .milliseconds(500), scheduler: RunLoop.main) .removeDuplicates() // Abonnement publisher .sink { [weak self] value in self?.label.text = "Vous avez saisi : \\(value)" } .store(in: &cancellables) }}Dans l'exemple, debounce est utilisé pour retarder la réaction à la saisie et removeDuplicates pour ignorer les valeurs répétées.
RxSwift : une alternative puissante
RxSwift est un port de ReactiveX pour Swift. Il offre un ensemble plus large d'opérateurs et prend en charge les versions plus anciennes d'iOS. Le même exemple avec RxSwift :
import RxSwiftimport RxCocoa
class ViewController: UIViewController { @IBOutlet weak var textField: UITextField! @IBOutlet weak var label: UILabel! private let disposeBag = DisposeBag()
override func viewDidLoad() { super.viewDidLoad() textField.rx.text .orEmpty .debounce(.milliseconds(500), scheduler: MainScheduler.instance) .distinctUntilChanged() .subscribe(onNext: { [weak self] text in self?.label.text = "Vous avez saisi : \\(text)" }) .disposed(by: disposeBag) }}Notez l'utilisation de rx.text (via RxCocoa) et distinctUntilChanged() — l'équivalent de removeDuplicates dans Combine.
Opérateurs clés
map/compactMap— transformation des valeurs.filter— ne laisse passer que les valeurs satisfaisant une condition.combineLatest— combine les dernières valeurs de plusieurs flux.zip— combine par paires les éléments de plusieurs flux.flatMap— transforme un flux en un autre flux (souvent utilisé pour les requêtes réseau).catch/retry— gestion des erreurs.