Event Bus et le pattern Observer en Swift (iOS/macOS)

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

Event Bus et le pattern Observer en Swift (iOS/macOS)



Dans le développement iOS et macOS, il est souvent nécessaire d'organiser une interaction faiblement couplée entre les composants de l'application. Le pattern Observer et son implémentation via un bus d'événements (Event Bus) sont un outil puissant pour créer une architecture flexible et évolutive. Dans cet article, nous allons voir comment implémenter un Event Bus en Swift, le comparer aux mécanismes intégrés d'Apple (NotificationCenter, Combine) et montrer des exemples pratiques pour iOS/macOS.



Qu'est-ce que l'Event Bus et le pattern Observer ?



Le pattern Observer définit une relation "un à plusieurs" entre les objets : lorsqu'un objet (l'éditeur) modifie son état, tous les objets dépendants (les abonnés) en sont automatiquement notifiés.



L'Event Bus (bus d'événements) est un mécanisme centralisé qui permet à n'importe quel composant d'envoyer des événements (publier) et de les recevoir (s'abonner), sans se connaître directement. Cela met en œuvre le principe de faible couplage (loose coupling).



Dans l'écosystème Apple, il existe déjà des solutions intégrées :

  • NotificationCenter — une implémentation classique d'Observer, mais avec des limitations en matière de typage et de sécurité.
  • Combine — un framework moderne pour la programmation réactive, offrant de puissants Publisher/Subscriber.

Cependant, un Event Bus fait maison offre un contrôle total et peut être plus facilement intégré dans des projets legacy.



Implémentation d'un Event Bus simple en Swift



Créons un bus d'événements universel utilisant des génériques et des références faibles pour éviter les fuites mémoire.



import Foundation

// Protocole pour les événementsprotocol Event { }

// Implémentation de l'Event Busfinal class EventBus { static let shared = EventBus() private var observers = [ObjectIdentifier: [WeakObserver]]() private init() { } // Abonnement à un événement func subscribe<T: Event>(observer: AnyObject, handler: @escaping (T) -> Void) { let id = ObjectIdentifier(T.self) let weakRef = WeakObserver(observer: observer, handler: { event in guard let castedEvent = event as? T else { return } handler(castedEvent) }) if observers[id] != nil { observers[id]?.append(weakRef) } else { observers[id] = [weakRef] } // Nettoyage des références mortes cleanDeadObservers(for: id) } // Publication d'un événement func publish<T: Event>(_ event: T) { let id = ObjectIdentifier(T.self) guard let observerList = observers[id] else { return } for weakObserver in observerList { weakObserver.handler?(event) } // Suppression des objets libérés cleanDeadObservers(for: id) } // Désabonnement func unsubscribe(observer: AnyObject, eventType: Event.Type) { let id = ObjectIdentifier(eventType) observers[id]?.removeAll { $0.observer === observer } } private func cleanDeadObservers(for id: ObjectIdentifier) { observers[id]?.removeAll { $0.observer == nil } }}

// Classe auxiliaire pour la référence faibleprivate class WeakObserver { weak var observer: AnyObject? var handler: ((Event) -> Void)? init(observer: AnyObject, handler: @escaping (Event) -> Void) { self.observer = observer self.handler = handler }}


Exemple d'utilisation



Définissons des événements personnalisés :



struct UserLoggedInEvent: Event {    let userId: String    let userName: String}

struct DataLoadedEvent: Event { let data: [String]}


Utilisation dans un ViewController :



class ProfileViewController: UIViewController {    override func                    

Recommendations