RxSwift — cos'è, concetti chiave e programmazione reattiva

Autore: IT Sectr Pubblicato: 2026-03-17 Tempo di lettura: 8 min

RxSwift è una libreria di programmazione reattiva per Swift che implementa il pattern Observable. Secondo ReactiveX, 2025, è l'implementazione più popolare di Reactive Extensions per l'ecosistema Apple. Observable funge da fonte di eventi, mentre Observer si sottoscrive per riceverli.

Punti chiave

  • RxSwift — un'implementazione di Reactive Extensions per Swift con supporto per Observable, Subject e oltre 300 operatori
  • Observable — una fonte di eventi che emette valori, errori o un segnale di completamento
  • Subject — contemporaneamente Observable e Observer, permette di inserire manualmente eventi nel flusso
  • DisposeBag — un meccanismo automatico di gestione della memoria che annulla le sottoscrizioni al dealloc
  • Schedulers — gestiscono i thread di esecuzione, permettendo di passare tra code principali e di background

Cos'è RxSwift?

RxSwift è una libreria di programmazione reattiva per il linguaggio Swift, portata da Reactive Extensions (Rx). Permette di descrivere programmi asincroni e guidati da eventi tramite Observable Sequence — una sequenza di dati disponibili nel tempo. Gli sviluppatori iOS usano RxSwift per gestire richieste di rete, eventi UI e dati in streaming senza callback annidati.

Observable e Observer

La base di RxSwift consiste in due protocolli chiave: ObservableType — una fonte di eventi che può emettere tre tipi di segnali: .next(value), .error(error) e .completed. Observer si sottoscrive a Observable tramite il metodo subscribe e riceve questi eventi. Questo modello è chiamato Reactive Streams e garantisce che nessun evento vada perso con una sottoscrizione corretta.

Operatori di trasformazione

RxSwift fornisce oltre 300 operatori per lavorare con i flussi: map trasforma ogni evento, filter lascia passare solo quelli corrispondenti, flatMap dispiega Observable annidati in un unico flusso. Gli operatori sono concatenati, creando una pipeline dichiarativa di elaborazione dati senza effetti collaterali.

Traits: Single, Completable, Maybe

Oltre all'Observable base, RxSwift fornisce tipi wrapper specializzati. Single emette esattamente un valore o un errore — ideale per richieste HTTP. Completable termina con successo o fallimento senza valore — per operazioni di scrittura. Maybe combina entrambi gli scenari: può terminare con valore, senza valore o con errore. Questi Traits semplificano la semantica e rendono il codice auto-documentante.

Come funziona la programmazione reattiva in RxSwift

La programmazione reattiva in RxSwift è costruita sul pattern Observer. ObservableSequence è analogo a Sequence della libreria standard, ma con accesso asincrono agli elementi. Il flusso di eventi viene passato attraverso una catena di operatori, ciascuno restituisce una nuova ObservableSequence senza mutare l'originale.

Catene di operatori

Gli operatori in RxSwift sono funzioni pure che prendono una ObservableSequence e ne restituiscono una nuova. Ad esempio, map crea una nuova sequenza applicando una trasformazione a ogni elemento. Combinando operatori, lo sviluppatore costruisce una pipeline dove i dati attraversano tutte le fasi di elaborazione senza variabili intermedie.

Schedulers e thread di esecuzione

Schedulers sono un'astrazione sui thread di esecuzione in RxSwift. Un Scheduler determina su quale thread il codice verrà eseguito: MainScheduler — il thread UI, SerialDispatchQueueScheduler — una coda di background. Gli operatori subscribeOn e observeOn specificano rispettivamente dove viene eseguito il lavoro e dove vengono elaborati i risultati.

Componenti principali di RxSwift

RxSwift include diversi tipi base, ognuno risolve il proprio compito nella pipeline reattiva. Single è un Observable che emette esattamente un valore o un errore, comodo per richieste di rete. Completable termina con successo o fallimento senza valore. Maybe combina le proprietà di Single e Completable.

Subject e Relay

Subject è un Observable caldo che funge anche da Observer. PublishSubject emette solo nuovi eventi agli iscritti, BehaviorSubject — l'ultimo evento più i nuovi. Relay è una variante di Subject che non emette .error o .completed, garantendo la continuità del flusso. BehaviorRelay memorizza il valore corrente ed è adatto per UI guidate dallo stato.

DisposeBag

DisposeBag è una collezione di Disposable che annulla automaticamente tutte le sottoscrizioni al proprio dealloc. In iOS, DisposeBag viene solitamente aggiunta a UIViewController o UIView. Quando la schermata viene chiusa, DisposeBag viene pulita — questo previene perdite di memoria e l'accesso a elementi UI inesistenti.

Esempi di codice RxSwift

Di seguito un esempio di creazione di un Observable da un array di dati usando l'operatore map per trasformare stringhe:

swift
let observable = Observable.of("Swift", "RxSwift", "Reactive")

observable
    .map { $0.uppercased() }
    .subscribe(onNext: { value in
        print("Received: \(value)")
    })
    .disposed(by: disposeBag)

Il secondo esempio mostra la combinazione di due richieste di rete usando zip — l'operatore aspetta che entrambi gli Observable emettano un valore e combina i risultati in una tupla:

swift
let first = fetchUser(id: "123")
let second = fetchPosts(userId: "123")

Observable
    .zip(first, second)
    .observe(on: MainScheduler.instance)
    .subscribe(onNext: { user, posts in
        updateUI(user: user, posts: posts)
    })
    .disposed(by: disposeBag)

Il terzo esempio mostra l'uso di BehaviorRelay per memorizzare lo stato e aggiornare automaticamente l'UI ai cambiamenti: ogni modifica state.accept() viene immediatamente trasmessa agli iscritti, ideale per pattern di Stato nell'architettura MVVM.

swift
let state = BehaviorRelay(value: "idle")

state
    .subscribe(onNext: { status in
        print("Status: \(status)")
    })
    .disposed(by: disposeBag)

state.accept("loading") // Prints: Status: loading

RxSwift vs altri approcci

RxSwift si differenzia dai metodi asincroni tradizionali (Delegation, NotificationCenter, Callback) per la sua natura dichiarativa e componibilità. A differenza di Combine, RxSwift supporta iOS 9+ e ha più operatori. Tuttavia, Combine è integrato in Foundation e SwiftUI a livello di linguaggio, dandogli un vantaggio nei nuovi progetti Apple.

Il principale vantaggio di RxSwift rispetto a GCD (Grand Central Dispatch) è la capacità di combinare e trasformare flussi di dati a livello di astrazione, invece di gestire manualmente le code. Tuttavia, RxSwift richiede l'apprendimento di concetti reattivi, aumentando la barriera d'ingresso per il team.

In pratica, RxSwift viene utilizzato in grandi progetti dove catene reattive collegano eventi UI, logica di business e interazione di rete in un'unica pipeline. Ad esempio, nelle applicazioni di trading, i flussi di quotazioni vengono elaborati tramite RxSwift: i tick arrivano da WebSocket, passano attraverso il filtraggio, vengono raggruppati per timeframe e visualizzati su un grafico in tempo reale. Questo scenario è difficile da implementare tramite Delegation o NotificationCenter senza perdere leggibilità.

Le alternative a RxSwift includono Combine (iOS 13+), AsyncSequence da Swift Concurrency (iOS 15+), oltre a librerie di terze parti come ReactiveSwift senza vincoli alle piattaforme Apple. La scelta dipende dalla versione minima supportata di iOS e dall'esperienza degli sviluppatori. Per i nuovi progetti iOS 15+, i team spesso scelgono AsyncSequence — non richiede installazione di librerie e utilizza costrutti nativi del linguaggio Swift.

I pattern architetturali con RxSwift seguono tipicamente MVVM o Clean Architecture. ViewModel contiene tutta la logica di business come catene Observable, View si sottoscrive ai dati trasformati. Il pattern Input-Output separa gli eventi di input (tocchi, input di testo) dagli stati di output (testo del pulsante, visibilità del loader). Questo approccio semplifica i test: ViewModel viene testato senza UI tramite Schedulers virtuali.

RxSwift è adatto sia per progetti piccoli con pochi schermi che per grandi applicazioni enterprise con decine di moduli. Nei grandi progetti, le catene reattive permeano l'intera architettura: dall'osservazione di UserDefaults tramite RxProperty alle richieste di rete attraverso Moya (un wrapper RxSwift su Alamofire). Ogni modulo è isolato e comunica tramite interfacce reattive, semplificando la sostituzione dell'implementazione senza modificare gli iscritti. Con un'architettura adeguata, RxSwift riduce la quantità di codice rispetto agli approcci classici, poiché non è necessario scrivere boilerplate per KVO, Target-Action o NotificationCenter.

RxSwift è attivamente utilizzato in progetti con RxDataSources — una libreria per il lavoro reattivo con UITableView e UICollectionView. RxDataSources calcola automaticamente la differenza tra insiemi vecchi e nuovi di celle e applica modifiche animate. Questo libera lo sviluppatore dal lavoro manuale con beginUpdates/endUpdates ed elimina i crash dovuti all'incoerenza dei dati.

Per il debug delle catene RxSwift, esiste l'operatore debug() — registra tutti gli eventi: subscribe, next, error, completed, dispose. È uno strumento indispensabile nello sviluppo di pipeline reattive complesse. debug(String) prende un identificatore che appare nei log. Per la profilazione della memoria, RxSwift.Resources.total mostra il numero totale di Observable e Disposable attivi nell'applicazione — aiuta a identificare perdite quando DisposeBag non viene pulita o un retain cycle mantiene una sottoscrizione. L'operatore aggiuntivo takeUntil(self.rx.deallocated) annulla automaticamente la sottoscrizione al dealloc dell'oggetto — questo è un ulteriore strato di protezione contro le perdite di memoria.

Best practice RxSwift

Quando si scrive codice RxSwift, è importante seguire il principio di singolo Observable per sottoscrizione: ogni ViewController non dovrebbe creare più di una Sottoscrizione allo stesso Observable — questo riduce il rischio di race condition. Per la memoizzazione degli Observable, si usa l'operatore share(), che trasforma un Observable freddo in caldo con un buffer replay di dimensione 1. Quando si lavora con risorse condivise, utilizzare connect() per controllare l'inizio dell'emissione — questo garantisce che tutti gli iscritti si connettano prima del primo evento.

Il test del codice RxSwift viene eseguito tramite TestScheduler — un Scheduler virtuale che permette di gestire il tempo. testScheduler.createHotObservable(values) crea un Observable con una sequenza predefinita di eventi per tempo virtuale. testScheduler.start() avvia l'elaborazione. TestScheduler permette di verificare in quale ordine e a quale timestamp virtuale si verificano gli eventi, senza ritardi reali, rendendo i test rapidi e deterministici.

Domande frequenti

Qual è la differenza tra Observable e Subject in RxSwift?

Observable è una fonte fredda: non emette eventi fino alla sottoscrizione. Subject è caldo: emette eventi indipendentemente dagli iscritti e permette l'inserimento manuale di valori tramite onNext. PublishSubject trasmette solo nuovi eventi, BehaviorSubject — l'ultimo più i nuovi.

Come previene DisposeBag le perdite di memoria in RxSwift?

DisposeBag memorizza tutte le sottoscrizioni Disposable. Quando DisposeBag viene deallocata (ad esempio, alla chiusura di un ViewController), tutte le sottoscrizioni memorizzate vengono automaticamente annullate. Questo garantisce che Observable non invierà un evento a un oggetto UI distrutto.

Cosa scegliere: RxSwift o Combine per un nuovo progetto iOS?

Se la versione minima di iOS è 13+ e il team conosce SwiftUI — scegliete Combine. Se il progetto supporta iOS 12 e inferiori o richiede un insieme maggiore di operatori — RxSwift. Combine offre una migliore integrazione con Foundation (URLSession, Timer, NotificationCenter).

Come funzionano gli Schedulers in RxSwift?

Schedulers astrattizzano i thread di esecuzione. subscribeOn specifica su quale Scheduler viene effettuata la sottoscrizione (di solito in background). observeOn determina su quale Scheduler vengono ricevuti gli eventi (spesso MainScheduler per aggiornamenti UI). SerialDispatchQueueScheduler funziona tramite GCD.

Si può usare RxSwift con SwiftUI?

Sì, RxSwift può essere integrato con SwiftUI tramite ObservableObject. Usate BehaviorRelay come proprietà @Published: la sottoscrizione al Relay trasmette le modifiche a Combine, e SwiftUI ridisegna la View tramite @ObservedObject. Questo è un pattern popolare di migrazione da UIKit a SwiftUI.

Riepilogo

  • RxSwift — una libreria di programmazione reattiva basata su Reactive Extensions e sul pattern Observable
  • Observable emette tre tipi di segnali: .next, .error e .completed
  • Subject (PublishSubject, BehaviorSubject) combina Observable e Observer per flussi caldi
  • DisposeBag gestisce il ciclo di vita delle sottoscrizioni e previene perdite di memoria
  • Operatori (map, filter, flatMap, zip) permettono di costruire catene di elaborazione dichiarative
  • Schedulers commutano l'esecuzione tra code di background e il thread UI
  • Per nuovi sviluppi iOS 13+, considerate Combine come alternativa integrata

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche