RxSwift ist eine reaktive Programmierbibliothek für iOS, die das Observable-Muster und funktionale Operatoren für die Arbeit mit asynchronen Datenströmen implementiert. Sie portiert die Konzepte von ReactiveX (Rx) in die Sprache Swift und bietet eine einheitliche API zur Verarbeitung von Ereignissen aus UI, Netzwerkanfragen, Datenbanken und Timern. Laut ReactiveX, 2025 wird die Bibliothek in mehr als 60.000 Projekten auf GitHub verwendet und bleibt der Standard für reaktive Programmierung in Swift bis zum Aufkommen von nativem Combine. RxSwift ersetzt Delegaten, Closures und Benachrichtigungen durch eine einzige Ereignisverarbeitungskette.
Wichtige Punkte
RxSwift ist der Swift-Port der ReactiveX-Bibliothek (Rx), die 2012 von Microsoft für .NET erstellt wurde. Die Kernidee von Rx besteht darin, jede asynchrone Datenquelle als Observable-Sequenz darzustellen, auf die funktionale Operatoren angewendet werden können. In der iOS-Entwicklung wird RxSwift verwendet, um UI-Ereignisse (Schaltflächentipps, Texteingabe, Gesten) ohne explizite Delegaten und Target-Action an die Anwendungslogik zu binden.
Die Bibliothek besteht aus drei Modulen: RxSwift (Kern — Observable, Operator, Scheduler), RxCocoa (UIKit-Integration — rx-Erweiterungen für UIButton, UITextField, UITableView) und RxRelay (Subject ohne Terminalereignisse). Diese Trennung ermöglicht die Verwendung des Kerns in serverseitigem Swift und Tests, wobei der UI-Wrapper nur für iOS-Anwendungen angeschlossen wird.
Laut der Umfrage Stack Overflow, 2025 gehört RxSwift zu den 5 am häufigsten verwendeten Drittanbieterbibliotheken für iOS. Der Hauptgrund für seine Beliebtheit ist die einheitliche Behandlung aller asynchronen Muster: Netzwerkanfragen über URLSession, Animationen über UIViewPropertyAnimator, Benachrichtigungen über NotificationCenter und Delegaten über DelegateProxy — all dies lässt sich auf ein Observable mit vorhersagbarem Lebenszyklus reduzieren.
Reaktive Programmierung ist ein Paradigma, bei dem das Programm auf Datenänderungen reagiert, anstatt sie abzufragen. Anstatt „Daten holen → verarbeiten → UI aktualisieren“ zu schreiben, beschreibt der Entwickler eine Transformationskette: „Wenn sich Daten ändern, wende Filter an, dann map, dann aktualisiere UI“. RxSwift implementiert dieses Paradigma durch Observable-Ketten mit fauler Ausführung — nichts passiert, bis ein Abonnent erscheint.
Observable ist der grundlegende Typ von RxSwift, der eine Abfolge von Ereignissen im Zeitverlauf darstellt. Observable kann drei Arten von Ereignissen senden: next (neuer Wert), error (Fehler, der den Stream beendet) und completed (erfolgreicher Abschluss). Es gibt endliche Observable (schließen nach dem Senden aller Werte ab) und unendliche Observable (z. B. UI-Ereignisse — schließen nie ab).
Der Lebenszyklus eines Observable umfasst drei Phasen: Erstellung (create, just, from), Transformation (Operatoren map, filter, flatMap) und Abonnement (subscribe). Ohne ein Abonnement führt Observable keine Aktionen aus — es ist eine faule Sequenz. Nach dem Abonnement beginnt Observable, Ereignisse an den Abonnenten zu senden, bis es abgeschlossen ist oder der Abonnent das Abonnement über Disposable kündigt.
import RxSwift
// Observable aus Array erstellen
let numbers = Observable.from([1, 2, 3, 4, 5])
// Transformation durch Operatoren
let squared = numbers
.filter { $0 % 2 == 0 }
.map { $0 * $0 }
// Abonnement mit Ereignisbehandlung
let disposable = squared
.subscribe(onNext: { print($0) },
onError: { print("Error: \($0)") },
onCompleted: { print("Done") })
Subject ist ein Typ, der sowohl ein Observable (abbonierbar) als auch ein Observer (Ereignisse sendbar) ist. RxSwift bietet vier Arten von Subject: PublishSubject (nur neue Ereignisse), BehaviorSubject (mit einem Anfangswert), ReplaySubject (puffert die letzten N Ereignisse) und AsyncSubject (nur der letzte Wert vor Abschluss). Subject ist nützlich für die Integration von imperativem Code (Closures, Delegaten) in eine reaktive Kette.
Disposable ist ein Token zur Kündigung des Abonnements. Wenn der Abonnent keine Ereignisse mehr empfangen möchte, ruft er disposable.dispose() auf. In der Praxis wird DisposeBag verwendet: eine Sammlung von Disposable, die bei der Deinitialisierung des Besitzers (z. B. UIViewController) automatisch alle Abonnements kündigt. Dies verhindert Speicherlecks, die bei der manuellen Verwaltung von Abonnements unvermeidlich sind.
| Subject-Typ | Anfangswert | Wiederholt an Abonnenten | Verwendung |
|---|---|---|---|
| PublishSubject | Nein | Nur neue Ereignisse | UI-Ereignisse, seltene Benachrichtigungen |
| BehaviorSubject | Ja | Letztes + neue | Zustand, Datenstrom |
| ReplaySubject | Nein | Puffer N + neue | Verlaufscaching |
| AsyncSubject | Nein | Nur letztes | Rechenaufgaben |
| PublishRelay | Nein | Nur neue | Ohne error/completed |
Operatoren in RxSwift sind Funktionen, die ein Observable nehmen und ein anderes Observable zurückgeben, wodurch der Datenstrom transformiert wird. Durch die Kombination von Operatoren erstellt der Entwickler deklarative Verarbeitungsketten ohne Zwischenvariablen und Wettlaufsituationen. Alle Operatoren sind faul: Die Kette wird bei der Beschreibung aufgebaut und beim Abonnement ausgeführt.
Transformationsoperatoren ändern jedes Ereignis im Stream. map wendet eine Funktion auf jedes Element an, flatMap entfaltet Observable von jedem Element in einen einzelnen flachen Stream, scan akkumuliert Zwischenergebnisse (ähnlich wie reduce, aber mit Ausgabe jedes Schritts). buffer gruppiert Elemente nach Zeit oder Anzahl, window teilt den Stream in verschachtelte Observable nach Fenstern auf.
// Beispiel einer Operatorkette: Suche mit 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)
Filteroperatoren lassen nur Ereignisse passieren, die eine Bedingung erfüllen. filter filtert nach Prädikat, distinctUntilChanged lässt nur Werte passieren, die sich vom vorherigen unterscheiden, take und takeWhile begrenzen die Anzahl der Ereignisse. skip und skipWhile überspringen die ersten N Ereignisse oder Ereignisse bis zum Eintreten einer Bedingung. Zur Fehlerbehandlung werden catchError (Abfangen und Ersetzen) und retry (Wiederholen der Sequenz bei Fehler) verwendet.
Kombinationsoperatoren fassen mehrere Observables zu einem zusammen. combineLatest führt die letzten Werte aus mehreren Streams zu einem Tupel zusammen, zip paart Elemente mit denselben Indizes, merge kombiniert mehrere Streams in der Reihenfolge des Ereigniseingangs zu einem. withLatestFrom kombiniert ein Ereignis aus dem Hauptstrom mit dem letzten Wert aus einem anderen Strom — nützlich für UI-Ereignisse mit aktuellem Zustand.
| Kategorie | Operator | Beschreibung |
|---|---|---|
| Transformation | map | Transformiert jeden Wert durch eine Funktion |
| Transformation | flatMap | Entfaltet verschachtelte Observables in einen flachen Stream |
| Filterung | filter | Lässt Werte nach Prädikat passieren |
| Filterung | distinctUntilChanged | Lässt nur geänderte Werte passieren |
| Kombination | combineLatest | Kombiniert letzte Werte aus 2+ Streams |
| Kombination | zip | Paart Elemente nach Index |
| Steuerung | debounce | Verzögert Ereignisse bis zu einer Pause im Stream |
| Steuerung | take | Nimmt die ersten N Ereignisse und schließt den Stream ab |
Scheduler in RxSwift ist eine Abstraktion über den Ausführungsthread (oder die Warteschlange). Scheduler bestimmt, in welchem Thread die Ereigniserstellung, Transformation und das Abonnement ausgeführt werden. Im Gegensatz zu GCD, wo der Entwickler explizit DispatchQueue angibt, verwendet RxSwift zwei Parameter: subscribeOn (in welchem Thread das Observable ausgeführt wird) und observeOn (in welchem Thread der Abonnent aufgerufen wird).
MainScheduler führt Code im Hauptthread aus — erforderlich für UIKit-Updates (alle UI-Änderungen müssen im Hauptthread stattfinden). SerialDispatchQueueScheduler kapselt eine serielle GCD-Warteschlange, ConcurrentDispatchQueueScheduler eine gleichzeitige. Für Hintergrundaufgaben wird ConcurrentDispatchQueueScheduler mit qos: .background oder .utility verwendet.
// Typisches Muster: Hintergrundarbeit + UI auf main
apiService.fetchData()
.subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
.observeOn(MainScheduler.instance)
.subscribe(onNext: { data in
self.tableView.reloadData()
self.loadingIndicator.stopAnimating()
})
.disposed(by: disposeBag)
Die richtige Verwendung von Scheduler verhindert die Blockierung der UI bei Netzwerkanfragen und aufwändigen Berechnungen. subscribeOn wirkt sich auf den gesamten Upstream aus (alle Operatoren vor observeOn werden im angegebenen Scheduler ausgeführt). observeOn schaltet den Downstream um — alle Operatoren nach observeOn werden im angegebenen Scheduler ausgeführt. Eine Kette kann mehrere observeOn haben, um zwischen Threads in verschiedenen Transformationsphasen zu wechseln.
SerialDispatchQueueScheduler garantiert die sequenzielle Verarbeitung von Ereignissen, was für die Threadsicherheit gemeinsamer Ressourcen wichtig ist. Für stark ausgelastete Operationen (Bildverarbeitung, JSON-Parsing) verwenden Sie ConcurrentDispatchQueueScheduler — RxSwift behält die Ereignisreihenfolge innerhalb eines Observable bei, aber verschiedene Observables können parallel verarbeitet werden.
RxSwift wird in iOS-Projekten am häufigsten verwendet, um die UI über reaktive Ketten an Daten zu binden. RxCocoa bietet rx-Erweiterungen für alle standardmäßigen UIKit-Komponenten: rx.tap für UIButton, rx.text für UITextField, rx.selectedRow für UIPickerView. Dies ermöglicht es, auf @IBAction und Delegaten zu verzichten und sie durch deklarative Abonnements zu ersetzen.
MVVM (Model-View-ViewModel) ist ein Architekturmuster, bei dem ViewModel den Zustand und die Geschäftslogik verwaltet und View die reaktiven Eigenschaften von ViewModel abonniert. RxSwift passt perfekt zu MVVM: ViewModel veröffentlicht Observable oder Driver für Daten, View abonniert sie über bind. ViewModel hat keinen Verweis auf View — es gibt Observable zurück, die View konsumiert.
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)
Netzwerkanfragen sind der zweithäufigste Anwendungsfall von RxSwift. URLSession.rx.response kapselt eine HTTP-Anfrage in ein Observable, das bei Erfolg (response, data) oder bei Fehler error zurückgibt. In Kombination mit Codable und dem map-Operator ergibt sich eine kompakte reaktive API-Schicht: Observable<MyModel> ohne Callbacks und Fehlerbehandlung in jeder Methode. Bei einem Netzwerkfehler wiederholt der retry(3)-Operator die Anfrage automatisch dreimal mit exponentieller Verzögerung.
Combine ist das native Apple-Framework, das in iOS 13 eingeführt wurde. Es löst dieselben Aufgaben wie RxSwift: Arbeiten mit asynchronen Ereignissen über Publisher, Subscriber und Operatoren. Combine hat jedoch entscheidende Unterschiede: strenge Fehlertypisierung über den Failure-Typ, integrierte Unterstützung für Swift Concurrency (async/await) und Integration mit SwiftUI über @Published und ObservableObject.
RxSwift punktet mit Abwärtskompatibilität — es unterstützt iOS 8+, während Combine iOS 13+ erfordert. RxSwift verfügt über ein reichhaltigeres Ökosystem an Drittanbietererweiterungen (RxDataSources, RxGesture, RxAnimated) und eine detaillierte Operatordokumentation. Für Projekte, die ältere iOS-Versionen unterstützen, bleibt RxSwift die einzige Wahl.
Für neue Projekte mit iOS 13+ empfiehlt Apple Combine. Es ist eng mit SwiftUI integriert, hat eine kleinere Binärgröße und offizielle Unterstützung. Die Migration bestehender RxSwift-Codebasis zu Combine erfordert jedoch das Umschreiben aller Observable → Publisher, und das RxCocoa-Ökosystem hat kein vollständiges Combine-Äquivalent — UIKit hat keine nativen Publisher für alle UI-Komponenten.
| Merkmal | RxSwift | Combine |
|---|---|---|
| Minimales iOS | iOS 8+ | iOS 13+ |
| Fehlertyp | Error (beliebig) | Generic Failure |
| UI-Erweiterungen | RxCocoa (UIKit, AppKit) | @Published (SwiftUI) |
| Operatoren | 400+ Operatoren | ~100 Operatoren |
| Swift Concurrency | Über Bridge | Native Unterstützung |
| Status | Drittanbieter | Apple offiziell |
Häufig gestellte Fragen
Observable ist eine Ereignisquelle mit fauler Ausführung. Subject ist sowohl ein Observable als auch ein Observer — Sie können es abonnieren und manuell neue Ereignisse senden. Subject ist nützlich für die Integration von imperativem Code in reaktive Ketten.
RxSwift wird gewählt, wenn iOS 11-12-Unterstützung benötigt wird, eine vorhandene RxSwift-Codebasis besteht oder ein reichhaltiges Operatoren-Ökosystem erforderlich ist (400+ gegenüber ~100 in Combine). Für neue Projekte unter iOS 13+ wird Combine bevorzugt.
DisposeBag ist eine Sammlung von Disposable-Tokens, die bei der Deinitialisierung des Besitzers automatisch alle Abonnements kündigt. Ohne DisposeBag erstellt das Abonnement einen starken Verweis auf die Closure, was zu Speicherlecks führt, wenn UIViewController zerstört wird.
Verwenden Sie catchError, um einen Fehler durch einen Standardwert zu ersetzen, retry, um die Observable-Ausführung zu wiederholen, materialize, um den Fehler in ein Ereignis umzuwandeln. In der UI-Ebene leiten Driver und Signal keine Fehler weiter — sie werden intern behandelt.
Driver ist ein spezieller Observable-Typ, der die Ausführung auf MainScheduler, Abwesenheit von Fehlern und gemeinsame Ressourcennutzung garantiert. Driver stellt sicher, dass UI-Updates im Hauptthread stattfinden. Observable bietet solche Garantien nicht — observeOn ist erforderlich.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch