RxSwift — cos'è, funzionalità e programmazione reattiva

Autore: IT Sectr Pubblicato: 2026-05-03 Tempo di lettura: 10 min

RxSwift è una libreria di programmazione reattiva per iOS che implementa il pattern Observable e operatori funzionali per lavorare con flussi di dati asincroni. Porta i concetti di ReactiveX (Rx) in Swift, fornendo un'API unificata per gestire eventi da UI, richieste di rete, database e timer. Secondo ReactiveX, 2025, la libreria è utilizzata in oltre 60.000 progetti su GitHub e rimane lo standard di programmazione reattiva per Swift fino all'avvento del Combine nativo. RxSwift sostituisce delegati, closure e notifiche con una singola catena di elaborazione degli eventi.

Punti chiave

  • RxSwift — implementazione di ReactiveX per Swift basata sul pattern Observable e catene di operatori
  • Observable — una fonte di eventi asincroni che può terminare con successo, con errore o infinitamente
  • Subject — un ibrido di Observable e Observer che consente di inviare manualmente eventi al flusso
  • Schedulers controllano su quale thread vengono eseguiti abbonamento, osservazione ed elaborazione eventi
  • Operatori map, flatMap, filter, combineLatest trasformano e combinano flussi senza condizioni di gara

Cos'è RxSwift?

RxSwift è il port Swift della libreria ReactiveX (Rx) creata da Microsoft per .NET nel 2012. L'idea centrale di Rx è rappresentare qualsiasi fonte di dati asincrona come una sequenza Observable a cui è possibile applicare operatori funzionali. Nello sviluppo iOS, RxSwift viene utilizzato per legare eventi UI (tocchi di pulsanti, input di testo, gesti) alla logica dell'applicazione senza delegati espliciti e target-action.

La libreria è composta da tre moduli: RxSwift (nucleo — Observable, Operator, Scheduler), RxCocoa (integrazione UIKit — estensioni rx per UIButton, UITextField, UITableView) e RxRelay (Subject senza eventi terminali). Questa separazione consente di utilizzare il nucleo in Swift lato server e nei test, collegando il wrapper UI solo per le applicazioni iOS.

Secondo il sondaggio Stack Overflow, 2025, RxSwift è tra le 5 librerie di terze parti più utilizzate per iOS. Il motivo principale della sua popolarità è la gestione uniforme di tutti i pattern asincroni: richieste di rete tramite URLSession, animazioni tramite UIViewPropertyAnimator, notifiche tramite NotificationCenter e delegati tramite DelegateProxy — tutto si riduce a un Observable con un ciclo di vita prevedibile.

Filosofia della programmazione reattiva

La programmazione reattiva è un paradigma in cui il programma reagisce ai cambiamenti dei dati anziché interrogarli. Invece di scrivere “ottenere dati → elaborare → aggiornare UI”, lo sviluppatore descrive una catena di trasformazioni: “quando i dati cambiano, applica filtro, poi map, poi aggiorna UI”. RxSwift implementa questo paradigma attraverso catene Observable con esecuzione pigra — non accade nulla finché non appare un abbonato.

Componenti chiave di RxSwift: Observable, Subject, Disposable

Observable è il tipo fondamentale di RxSwift che rappresenta una sequenza di eventi nel tempo. Observable può inviare tre tipi di eventi: next (nuovo valore), error (errore che termina il flusso) e completed (completamento riuscito). Esistono Observable finiti (terminano dopo l'invio di tutti i valori) e Observable infiniti (ad esempio, eventi UI — non terminano mai).

Observable e il suo ciclo di vita

Il ciclo di vita di un Observable comprende tre fasi: creazione (create, just, from), trasformazione (operatori map, filter, flatMap) e abbonamento (subscribe). Senza un abbonamento, Observable non esegue alcuna azione — è una sequenza pigra. Dopo l'abbonamento, Observable inizia a inviare eventi all'abbonato fino al completamento o fino a quando l'abbonato annulla l'abbonamento tramite Disposable.

swift
import RxSwift

// Creare Observable da array
let numbers = Observable.from([1, 2, 3, 4, 5])

// Trasformazione tramite operatori
let squared = numbers
    .filter { $0 % 2 == 0 }
    .map { $0 * $0 }

// Abbonamento con gestione eventi
let disposable = squared
    .subscribe(onNext: { print($0) },
               onError: { print("Error: \($0)") },
               onCompleted: { print("Done") })

Subject è un tipo che è sia un Observable (a cui ci si può abbonare) sia un Observer (a cui si possono inviare eventi). RxSwift fornisce quattro tipi di Subject: PublishSubject (solo nuovi eventi), BehaviorSubject (con un valore iniziale), ReplaySubject (bufferizza gli ultimi N eventi) e AsyncSubject (solo l'ultimo valore prima del completamento). Subject è utile per integrare codice imperativo (closure, delegati) in una catena reattiva.

Disposable è un token di cancellazione dell'abbonamento. Quando l'abbonato non desidera più ricevere eventi, chiama disposable.dispose(). In pratica, si usa DisposeBag: una raccolta di Disposable che annulla automaticamente tutti gli abbonamenti alla deinizializzazione del proprietario (ad esempio, UIViewController). Ciò previene perdite di memoria inevitabili con la gestione manuale degli abbonamenti.

Tipo di SubjectValore inizialeReinvia all'abbonatoCaso d'uso
PublishSubjectNoSolo nuovi eventiEventi UI, notifiche rare
BehaviorSubjectUltimo + nuoviStato, flusso di dati
ReplaySubjectNoBuffer N + nuoviCaching della cronologia
AsyncSubjectNoSolo ultimoAttività computazionali
PublishRelayNoSolo nuoviSenza error/completed

Operatori di trasformazione e filtraggio dei flussi

Gli operatori in RxSwift sono funzioni che prendono un Observable e restituiscono un altro Observable, trasformando il flusso di dati. Combinando operatori, lo sviluppatore costruisce catene di elaborazione dichiarative senza variabili intermedie e condizioni di gara. Tutti gli operatori sono pigri: la catena viene costruita durante la descrizione ed eseguita all'abbonamento.

Gli operatori di trasformazione modificano ogni evento nel flusso. map applica una funzione a ogni elemento, flatMap dispiega Observable da ogni elemento in un singolo flusso piatto, scan accumula risultati intermedi (simile a reduce ma emettendo ogni passaggio). buffer raggruppa elementi per tempo o quantità, window divide il flusso in Observable annidati per finestre.

swift
// Esempio di catena di operatori: ricerca con 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)

Gli operatori di filtraggio lasciano passare solo gli eventi che soddisfano una condizione. filter filtra per predicato, distinctUntilChanged lascia passare solo valori diversi dal precedente, take e takeWhile limitano il numero di eventi. skip e skipWhile saltano i primi N eventi o eventi fino al soddisfacimento di una condizione. Per la gestione degli errori si usano catchError (intercettare e sostituire) e retry (riprovare la sequenza in caso di errore).

Gli operatori di combinazione combinano più Observable in uno. combineLatest unisce gli ultimi valori da più flussi in una tupla, zip accoppia elementi con gli stessi indici, merge combina più flussi in uno nell'ordine di arrivo degli eventi. withLatestFrom combina un evento dal flusso principale con l'ultimo valore di un altro flusso — utile per eventi UI con stato corrente.

CategoriaOperatoreDescrizione
TrasformazionemapTrasforma ogni valore tramite una funzione
TrasformazioneflatMapDispiega Observable annidati in un flusso piatto
FiltraggiofilterLascia passare valori per predicato
FiltraggiodistinctUntilChangedLascia passare solo valori modificati
CombinazionecombineLatestCombina ultimi valori da 2+ flussi
CombinazionezipAccoppia elementi per indice
ControllodebounceRitarda eventi fino a una pausa nel flusso
ControllotakePrende i primi N eventi e completa il flusso

Schedulers e gestione dei thread

Scheduler in RxSwift è un'astrazione sul thread di esecuzione (o coda). Scheduler determina su quale thread vengono eseguiti la creazione di eventi, la trasformazione e l'abbonamento. A differenza di GCD, dove lo sviluppatore specifica esplicitamente DispatchQueue, RxSwift utilizza due parametri: subscribeOn (su quale thread viene eseguito Observable) e observeOn (su quale thread viene chiamato l'abbonato).

MainScheduler e BackgroundScheduler

MainScheduler esegue il codice sul thread principale — obbligatorio per gli aggiornamenti UIKit (tutte le modifiche UI devono avvenire sul thread principale). SerialDispatchQueueScheduler incapsula una coda GCD seriale, ConcurrentDispatchQueueScheduler una coda concorrente. Per le attività in background si usa ConcurrentDispatchQueueScheduler con qos: .background o .utility.

swift
// Pattern tipico: lavoro in background + UI su main
apiService.fetchData()
    .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
    .observeOn(MainScheduler.instance)
    .subscribe(onNext: { data in
        self.tableView.reloadData()
        self.loadingIndicator.stopAnimating()
    })
    .disposed(by: disposeBag)

L'uso corretto di Scheduler previene il blocco dell'UI durante richieste di rete e calcoli pesanti. subscribeOn influenza tutto l'upstream (tutti gli operatori prima di observeOn vengono eseguiti sullo scheduler specificato). observeOn commuta il downstream — tutti gli operatori dopo observeOn vengono eseguiti sullo scheduler specificato. Una catena può avere più observeOn per commutare tra thread in diverse fasi di trasformazione.

SerialDispatchQueueScheduler garantisce l'elaborazione sequenziale degli eventi, importante per la thread safety delle risorse condivise. Per operazioni ad alto carico (elaborazione immagini, parsing JSON) utilizzare ConcurrentDispatchQueueScheduler — RxSwift manterrà l'ordine degli eventi all'interno di un Observable, ma diversi Observable possono essere elaborati in parallelo.

Applicazione pratica di RxSwift in iOS

RxSwift nei progetti iOS viene spesso utilizzato per legare l'UI ai dati attraverso catene reattive. RxCocoa fornisce estensioni rx per tutti i componenti UIKit standard: rx.tap per UIButton, rx.text per UITextField, rx.selectedRow per UIPickerView. Ciò consente di abbandonare @IBAction e delegati, sostituendoli con abbonamenti dichiarativi.

RxSwift con MVVM

MVVM (Model-View-ViewModel) è un pattern architetturale in cui ViewModel gestisce lo stato e la logica di business, e View si abbona alle proprietà reattive di ViewModel. RxSwift si adatta perfettamente a MVVM: ViewModel pubblica Observable o Driver per i dati, View vi si abbona tramite bind. ViewModel non ha riferimenti a View — restituisce Observable che View consuma.

swift
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
            }
    }
}

// In ViewController:
viewModel.isFormValid
    .bind(to: loginButton.rx.isEnabled)
    .disposed(by: disposeBag)

Le richieste di rete sono il secondo caso d'uso più comune di RxSwift. URLSession.rx.response incapsula una richiesta HTTP in un Observable che restituisce (response, data) in caso di successo o error in caso di fallimento. In combinazione con Codable e l'operatore map, si ottiene un livello API reattivo compatto: Observable<MyModel> senza callback e gestione degli errori in ogni metodo. In caso di errore di rete, l'operatore retry(3) riprova automaticamente la richiesta tre volte con backoff esponenziale.

RxSwift vs Combine

Combine è il framework nativo di Apple introdotto in iOS 13. Risolve gli stessi compiti di RxSwift: lavorare con eventi asincroni tramite Publisher, Subscriber e operatori. Tuttavia, Combine ha differenze chiave: tipizzazione rigorosa degli errori tramite il tipo Failure, supporto integrato per Swift Concurrency (async/await) e integrazione con SwiftUI tramite @Published e ObservableObject.

RxSwift vince in compatibilità all'indietro — supporta iOS 8+, mentre Combine richiede iOS 13+. RxSwift ha un ecosistema più ricco di estensioni di terze parti (RxDataSources, RxGesture, RxAnimated) e una documentazione dettagliata degli operatori. Per i progetti che supportano versioni iOS precedenti, RxSwift rimane l'unica scelta.

Per i nuovi progetti con iOS 13+, Apple raccomanda Combine. È strettamente integrato con SwiftUI, ha una dimensione binaria più piccola e supporto ufficiale. Tuttavia, la migrazione del codice RxSwift esistente a Combine richiede la riscrittura di tutti gli Observable → Publisher, e l'ecosistema RxCocoa non ha un equivalente completo in Combine — UIKit non ha Publisher nativo per tutti i componenti UI.

CaratteristicaRxSwiftCombine
iOS minimoiOS 8+iOS 13+
Tipo di erroreError (qualsiasi)Generic Failure
Estensioni UIRxCocoa (UIKit, AppKit)@Published (SwiftUI)
Operatori400+ operatori~100 operatori
Swift ConcurrencyTramite bridgeSupporto nativo
StatoTerze partiApple ufficiale

Domande frequenti

Qual è la differenza tra Observable e Subject in RxSwift?

Observable è una fonte di eventi con esecuzione pigra. Subject è sia un Observable che un Observer — puoi abbonarti e inviare manualmente nuovi eventi. Subject è utile per integrare codice imperativo in catene reattive.

Quando usare RxSwift invece di Combine?

RxSwift viene scelto quando è necessario il supporto per iOS 11-12, quando esiste un codebase RxSwift esistente o quando è necessario un ricco ecosistema di operatori (400+ contro ~100 in Combine). Per i nuovi progetti su iOS 13+, Combine è preferito.

Cos'è DisposeBag e a cosa serve?

DisposeBag è una raccolta di token Disposable che annulla automaticamente tutti gli abbonamenti alla deinizializzazione del proprietario. Senza DisposeBag, l'abbonamento crea un forte riferimento alla closure, causando perdite di memoria quando UIViewController viene distrutto.

Come gestire gli errori in RxSwift?

Usa catchError per sostituire un errore con un valore predefinito, retry per riprovare l'esecuzione di Observable, materialize per trasformare l'errore in un evento. Nel layer UI, Driver e Signal non trasmettono errori — vengono gestiti internamente.

Come differisce Driver da Observable in RxCocoa?

Driver è un tipo speciale di Observable che garantisce l'esecuzione su MainScheduler, assenza di errori e condivisione delle risorse. Driver garantisce che gli aggiornamenti UI avvengano sul thread principale. Observable non offre tali garanzie — è necessario observeOn.

Riepilogo

  • RxSwift è una libreria di programmazione reattiva per iOS che implementa il pattern Observable e 400+ operatori di trasformazione
  • Observable, Subject, Disposable sono tre tipi fondamentali che costituiscono la base di tutte le catene reattive
  • Operatori map, flatMap, filter, combineLatest, debounce consentono di costruire catene dichiarative senza condizioni di gara
  • Schedulers (subscribeOn / observeOn) gestiscono i thread di esecuzione, prevenendo il blocco dell'UI
  • RxCocoa fornisce estensioni rx per UIKit, sostituendo delegati e target-action con abbonamenti reattivi
  • Combine è l'alternativa nativa di Apple per iOS 13+, ma RxSwift rimane rilevante per versioni precedenti

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