RxSwift — wat is het, mogelijkheden en reactief programmeren

Auteur: IT Sectr Gepubliceerd: 2026-05-03 Leestijd: 10 min

RxSwift is een bibliotheek voor reactief programmeren voor iOS die het Observable-patroon en functionele operatoren implementeert voor het werken met asynchrone gegevensstromen. Het port de concepten van ReactiveX (Rx) naar Swift en biedt een uniforme API voor het verwerken van UI-gebeurtenissen, netwerkverzoeken, databases en timers. Volgens ReactiveX, 2025 wordt de bibliotheek gebruikt in meer dan 60.000 projecten op GitHub en blijft het de standaard voor reactief programmeren voor Swift tot de komst van native Combine. RxSwift vervangt delegaten, closures en meldingen door een uniforme keten voor gebeurtenisverwerking.

Belangrijkste punten

  • RxSwift — implementatie van ReactiveX voor Swift, gebaseerd op het Observable-patroon en operator-ketens
  • Observable — bron van asynchrone gebeurtenissen die succesvol, met een fout of oneindig kan eindigen
  • Subject — hybride van Observable en Observer waarmee handmatig gebeurtenissen naar de stroom kunnen worden verzonden
  • Schedulers beheren op welke thread abonneren, observeren en verwerken plaatsvindt
  • Operatoren map, flatMap, filter, combineLatest transformeren en combineren stromen zonder race-condities

Wat is RxSwift?

RxSwift is de Swift-port van de ReactiveX (Rx)-bibliotheek, gemaakt door Microsoft voor .NET in 2012. Het hoofdidee van Rx is om elke asynchrone gegevensbron voor te stellen als een Observable-reeks waarop functionele operatoren kunnen worden toegepast. In iOS-ontwikkeling wordt RxSwift gebruikt om UI-gebeurtenissen (knopdrukken, tekstinvoer, gebaren) te koppelen aan de applicatielogica zonder expliciete delegaten en target-action.

De bibliotheek bestaat uit drie modules: RxSwift (kern — Observable, Operator, Scheduler), RxCocoa (integratie met UIKit — rx-extensies voor UIButton, UITextField, UITableView) en RxRelay (Subject zonder terminale gebeurtenissen). Deze verdeling maakt het mogelijk om de kern te gebruiken in server-Swift en tests, terwijl de UI-koppeling alleen voor iOS-applicaties wordt aangesloten.

Volgens de Stack Overflow, 2025-enquête behoort RxSwift tot de top 5 meest gebruikte externe bibliotheken voor iOS. De belangrijkste reden voor populariteit is de uniforme verwerking van alle asynchrone patronen: netwerkverzoeken via URLSession, animaties via UIViewPropertyAnimator, meldingen via NotificationCenter en delegaten via DelegateProxy — alles wordt teruggebracht tot Observable met een voorspelbare levenscyclus.

Filosofie van reactief programmeren

Reactief programmeren is een paradigma waarbij het programma reageert op gegevenswijzigingen in plaats van ze te pollen. In plaats van “gegevens ophalen → verwerken → UI bijwerken” te schrijven, beschrijft de ontwikkelaar een transformatieketen: “wanneer gegevens veranderen, pas filter toe, dan map, dan werk UI bij”. RxSwift implementeert dit paradigma via Observable-ketens met luie uitvoering — er gebeurt niets totdat er een abonnee verschijnt.

Belangrijkste componenten van RxSwift: Observable, Subject, Disposable

Observable is het fundamentele type van RxSwift dat een reeks gebeurtenissen in de tijd vertegenwoordigt. Observable kan drie soorten gebeurtenissen verzenden: next (nieuwe waarde), error (fout, beëindigt de stroom) en completed (succesvolle voltooiing). Er bestaan finite Observable (eindigen na het verzenden van alle waarden) en infinite Observable (bijv. UI-gebeurtenissen — eindigen nooit).

Observable en zijn levenscyclus

Levenscyclus van Observable omvat drie fasen: creatie (create, just, from), transformatie (operatoren map, filter, flatMap) en abonneren (subscribe). Zonder abonnement voert Observable geen acties uit — het is een luie reeks. Na abonneren begint Observable gebeurtenissen naar de abonnee te sturen totdat het eindigt of de abonnee het abonnement opzegt via Disposable.

swift
import RxSwift

// Observable maken van een array
let numbers = Observable.from([1, 2, 3, 4, 5])

// Transformatie via operatoren
let squared = numbers
    .filter { $0 % 2 == 0 }
    .map { $0 * $0 }

// Abonneren met gebeurtenisafhandeling
let disposable = squared
    .subscribe(onNext: { print($0) },
               onError: { print("Error: \($0)") },
               onCompleted: { print("Done") })

Subject is een type dat tegelijkertijd Observable (men kan erop abonneren) en Observer (men kan er gebeurtenissen naartoe sturen) is. RxSwift biedt vier typen Subject: PublishSubject (alleen nieuwe gebeurtenissen), BehaviorSubject (met beginwaarde), ReplaySubject (bufferen van laatste N gebeurtenissen) en AsyncSubject (alleen laatste waarde voor voltooiing). Subject is handig voor integratie van imperatieve code (closures, delegaten) in de reactieve keten.

Disposable is een token voor het opzeggen van een abonnement. Wanneer de abonnee geen gebeurtenissen meer wil ontvangen, roept hij disposable.dispose() aan. In de praktijk wordt DisposeBag gebruikt: een verzameling Disposable die automatisch alle abonnementen opzegt bij deinitialisatie van de eigenaar (bijv. UIViewController). Dit voorkomt geheugenlekken die onvermijdelijk zijn bij handmatig beheer van abonnementen.

Subject-typeBeginwaardeHerhaalt aan abonneeGebruik
PublishSubjectNeeAlleen nieuwe gebeurtenissenUI-gebeurtenissen, zeldzame meldingen
BehaviorSubjectJaLaatste + nieuweToestand, gegevensstroom
ReplaySubjectNeeBuffer N + nieuweGeschiedenis cachen
AsyncSubjectNeeAlleen laatsteBerekeningstaken
PublishRelayNeeAlleen nieuweZonder error/completed

Operatoren voor transformatie en filtering van stromen

Operatoren van RxSwift zijn functies die één Observable nemen en een andere Observable retourneren, waarbij de gegevensstroom wordt getransformeerd. Door operatoren te combineren, bouwt de ontwikkelaar declaratieve verwerkingsketens zonder tussenliggende variabelen en race-condities. Alle operatoren zijn lui: de keten wordt opgebouwd tijdens het beschrijven en uitgevoerd tijdens het abonneren.

Transformatie-operatoren wijzigen elke gebeurtenis in de stroom. map past een functie toe op elk element, flatMap vouwt Observable van elk element uit in één platte stroom, scan accumuleert het tussenresultaat (analoog aan reduce, maar met emissie van elke stap). buffer groepeert elementen op tijd of hoeveelheid, window verdeelt de stroom in geneste Observable per venster.

swift
// Voorbeeld van operatorketen: zoeken met 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)

Filter-operatoren laten alleen gebeurtenissen door die aan de voorwaarde voldoen. filter scheidt op predicaat, distinctUntilChanged laat alleen waarden door die verschillen van de vorige, take en takeWhile beperken het aantal gebeurtenissen. skip en skipWhile slaan de eerste N gebeurtenissen of gebeurtenissen tot aan de voorwaarde over. Voor foutafhandeling worden catchError (opvangen en vervangen) en retry (herhalen van de reeks bij fout) gebruikt.

Combinatie-operatoren voegen meerdere Observable samen tot één. combineLatest combineert de laatste waarden uit meerdere stromen in een tuple, zip combineert elementen paarsgewijs met dezelfde indices, merge voegt meerdere stromen samen in de volgorde van binnenkomst van gebeurtenissen. withLatestFrom combineert een gebeurtenis uit de hoofdstroom met de laatste waarde uit een andere stroom — handig voor UI-gebeurtenissen met huidige toestand.

CategorieOperatorWat het doet
TransformatiemapTransformeert elke waarde via een functie
TransformatieflatMapVouwt geneste Observable uit in platte stroom
FilterenfilterLaat waarden door op basis van predicaat
FilterendistinctUntilChangedLaat alleen gewijzigde waarden door
CombinerencombineLatestCombineert laatste waarden uit 2+ stromen
CombinerenzipCombineert elementen paarsgewijs op index
BeheerdebounceVertraagt gebeurtenissen tot pauze in stroom
BeheertakeNeemt eerste N gebeurtenissen en beëindigt stroom

Schedulers en beheer van uitvoeringsthreads

Scheduler in RxSwift is een abstractie boven een uitvoeringsthread (of wachtrij). Scheduler bepaalt op welke thread het maken van gebeurtenissen, transformatie en abonneren plaatsvindt. In tegenstelling tot GCD, waar de ontwikkelaar expliciet DispatchQueue aangeeft, gebruikt RxSwift twee parameters: subscribeOn (op welke thread Observable wordt uitgevoerd) en observeOn (op welke thread de abonnee wordt aangeroepen).

MainScheduler en BackgroundScheduler

MainScheduler voert code uit op de hoofdthread — verplicht voor het bijwerken van UIKit (alle UI-wijzigingen moeten op de main thread plaatsvinden). SerialDispatchQueueScheduler wikkelt een sequentiële GCD-wachtrij in, ConcurrentDispatchQueueScheduler een parallelle. Voor achtergrondtaken wordt ConcurrentDispatchQueueScheduler met qos: .background of .utility gebruikt.

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

Correct gebruik van Scheduler voorkomt UI-blokkering bij netwerkverzoeken en zware berekeningen. subscribeOn beïnvloedt de hele upstream (alle operatoren tot observeOn worden uitgevoerd op de aangegeven planner). observeOn schakelt downstream — alle operatoren na observeOn worden uitgevoerd op de aangegeven planner. In de keten kunnen meerdere observeOn voorkomen voor het schakelen tussen threads in verschillende transformatiefasen.

SerialDispatchQueueScheduler garandeert sequentiële verwerking van gebeurtenissen, wat belangrijk is voor threadveiligheid van gedeelde bronnen. Voor zware bewerkingen (beeldverwerking, JSON-parsing) gebruik ConcurrentDispatchQueueScheduler — RxSwift behoudt de volgorde van gebeurtenissen binnen één Observable, maar verschillende Observable kunnen parallel worden verwerkt.

Praktische toepassing van RxSwift in iOS

RxSwift wordt in iOS-projecten het meest gebruikt voor het koppelen van UI aan gegevens via reactieve ketens. RxCocoa biedt rx-extensies voor alle standaard UIKit-componenten: rx.tap voor UIButton, rx.text voor UITextField, rx.selectedRow voor UIPickerView. Dit maakt het mogelijk om @IBAction en delegaten te vervangen door declaratieve abonnementen.

RxSwift in combinatie met MVVM

MVVM (Model-View-ViewModel) is een architectuurpatroon waarin ViewModel de toestand en bedrijfslogica beheert en View zich abonneert op de reactieve eigenschappen van ViewModel. RxSwift past perfect in MVVM: ViewModel publiceert Observable of Driver voor gegevens, View abonneert zich erop via bind. ViewModel heeft geen verwijzing naar View — het retourneert Observable die View consumeert.

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)

Netwerkverzoeken zijn het tweede meest voorkomende toepassingsgebied van RxSwift. URLSession.rx.response wikkelt een HTTP-verzoek in een Observable dat (response, data) retourneert bij succes of error bij mislukking. In combinatie met Codable en de operator map krijgen we een compacte reactieve API-laag: Observable<MyModel> zonder callbacks en foutafhandeling in elke methode. Bij een netwerkfout herhaalt de operator retry(3) het verzoek automatisch drie keer met exponentiële vertraging.

RxSwift vs Combine

Combine is een native Apple-framework, geïntroduceerd in iOS 13. Het lost dezelfde taken op als RxSwift: werken met asynchrone gebeurtenissen via Publisher, Subscriber en operatoren. Combine heeft echter belangrijke verschillen: strikte typering van fouten via het Failure-type, ingebouwde ondersteuning voor Swift Concurrency (async/await) en integratie met SwiftUI via @Published en ObservableObject.

RxSwift wint in achterwaartse compatibiliteit — het ondersteunt iOS 8+, terwijl Combine iOS 13+ vereist. RxSwift heeft een rijker ecosysteem van externe extensies (RxDataSources, RxGesture, RxAnimated) en gedetailleerde documentatie van operatoren. Voor projecten die oudere iOS-versies ondersteunen, blijft RxSwift de enige keuze.

Voor nieuwe projecten met iOS 13+ beveelt Apple Combine aan. Het is nauw geïntegreerd met SwiftUI, heeft een kleinere binaire grootte en officiële ondersteuning. Het migreren van bestaande RxSwift-code naar Combine vereist echter het herschrijven van alle Observable → Publisher, en het RxCocoa-ecosysteem heeft geen volledig equivalent in Combine — UIKit heeft geen native Publisher voor alle UI-componenten.

KenmerkRxSwiftCombine
Minimale iOSiOS 8+iOS 13+
FouttypeError (willekeurig)Generic Failure
UI-extensiesRxCocoa (UIKit, AppKit)@Published (SwiftUI)
Operatoren400+ operatoren~100 operatoren
Swift ConcurrencyVia brugNative ondersteuning
StatusExternOfficieel Apple

Veelgestelde vragen

Wat is het verschil tussen Observable en Subject in RxSwift?

Observable is een gebeurtenisbron met luie uitvoering. Subject is tegelijkertijd Observable en Observer — u kunt erop abonneren en er handmatig nieuwe gebeurtenissen naartoe sturen. Subject is handig voor integratie van imperatieve code in reactieve ketens.

Wanneer RxSwift gebruiken in plaats van Combine?

RxSwift wordt gekozen bij ondersteuning van iOS 11-12, bij een bestaande RxSwift-codebasis of bij behoefte aan een rijk operatoren-ecosysteem (400+ versus ~100 in Combine). Voor nieuwe projecten op iOS 13+ heeft Combine de voorkeur.

Wat is DisposeBag en waarvoor dient het?

DisposeBag is een verzameling Disposable-tokens die automatisch alle abonnementen opzegt bij deinitialisatie van de eigenaar. Zonder DisposeBag maakt een abonnement een sterke verwijzing naar de closure, wat leidt tot geheugenlekken bij vernietiging van UIViewController.

Hoe fouten afhandelen in RxSwift?

Gebruik catchError om een fout te vervangen door een standaardwaarde, retry voor heruitvoering van Observable, materialize om een fout om te zetten in een gebeurtenis. In de UI-laag geven Driver en Signal geen fouten door — ze worden intern afgehandeld.

Waarin verschilt Driver van Observable in RxCocoa?

Driver is een speciaal type Observable dat uitvoering op MainScheduler, afwezigheid van fouten en delen van bronnen garandeert. Driver garandeert dat UI-updates op de hoofdthread plaatsvinden. Observable geeft dergelijke garanties niet — observeOn is vereist.

Samenvatting

  • RxSwift — bibliotheek voor reactief programmeren voor iOS die het Observable-patroon en 400+ transformatie-operatoren implementeert
  • Observable, Subject, Disposable — drie fundamentele typen die de basis vormen van alle reactieve ketens
  • Operatoren map, flatMap, filter, combineLatest, debounce maken declaratieve ketens mogelijk zonder race-condities
  • Schedulers (subscribeOn / observeOn) beheren uitvoeringsthreads en voorkomen UI-blokkering
  • RxCocoa biedt rx-extensies voor UIKit die delegaten en target-action vervangen door reactieve abonnementen
  • Combine — native alternatief van Apple voor iOS 13+, maar RxSwift blijft relevant voor oudere versies

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook