Reaktive Programmierung in Swift (iOS/macOS): Combine und RxSwift
Reaktive Programmierung ist ein Paradigma, das auf der Arbeit mit asynchronen Datenströmen und der Verbreitung von Änderungen basiert. Im Apple-Ökosystem für iOS und macOS sind die wichtigsten Werkzeuge das native Framework Combine (seit iOS 13/macOS 10.15) und die Drittanbieter-Bibliothek RxSwift. Beide ermöglichen es, deklarativen, prägnanten und leicht testbaren Code zu schreiben und den Entwickler von „Callback Hell“ und komplexem Zustandsmanagement zu befreien.
Grundlegende Konzepte
- Publisher (Herausgeber) — eine Datenquelle, die Werte, Abschluss oder Fehler senden kann.
- Subscriber (Abonnent) — empfängt Daten vom Publisher und reagiert darauf.
- Operator (Operator) — eine Funktion zur Transformation des Streams (map, filter, combineLatest, debounce usw.).
- Subject — ein Hybrid, der sowohl Ereignisse empfangen als auch senden kann (PassthroughSubject, CurrentValueSubject).
- Scheduler (Planer) — bestimmt, in welchem Thread der Code ausgeführt wird.
Combine: nativens Framework von Apple
Combine ist in Foundation integriert und arbeitet mit Publisher und Subscriber. Ein Beispiel für die Verwendung zur Verarbeitung eines Textfeldes:
import Combineimport UIKit
class ViewController: UIViewController { @IBOutlet weak var textField: UITextField! @IBOutlet weak var label: UILabel! private var cancellables = Set<AnyCancellable>()
override func viewDidLoad() { super.viewDidLoad() // Erstellen eines Publishers aus NotificationCenter let publisher = NotificationCenter.default .publisher(for: UITextField.textDidChangeNotification, object: textField) .compactMap { ($0.object as? UITextField)?.text } .debounce(for: .milliseconds(500), scheduler: RunLoop.main) .removeDuplicates() // Abonnieren publisher .sink { [weak self] value in self?.label.text = "Sie haben eingegeben: \\(value)" } .store(in: &cancellables) }}Im Beispiel wird debounce verwendet, um die Reaktion auf die Eingabe zu verzögern, und removeDuplicates, um doppelte Werte zu ignorieren.
RxSwift: eine leistungsstarke Alternative
RxSwift ist ein Port von ReactiveX für Swift. Es bietet einen breiteren Satz von Operatoren und unterstützt ältere iOS-Versionen. Das gleiche Beispiel mit RxSwift:
import RxSwiftimport RxCocoa
class ViewController: UIViewController { @IBOutlet weak var textField: UITextField! @IBOutlet weak var label: UILabel! private let disposeBag = DisposeBag()
override func viewDidLoad() { super.viewDidLoad() textField.rx.text .orEmpty .debounce(.milliseconds(500), scheduler: MainScheduler.instance) .distinctUntilChanged() .subscribe(onNext: { [weak self] text in self?.label.text = "Sie haben eingegeben: \\(text)" }) .disposed(by: disposeBag) }}Beachten Sie die Verwendung von rx.text (über RxCocoa) und distinctUntilChanged() — das Analogon zu removeDuplicates in Combine.
Wichtige Operatoren
map/compactMap— Transformation von Werten.filter— lässt nur Werte durch, die eine Bedingung erfüllen.combineLatest— kombiniert die letzten Werte aus mehreren Streams.zip— kombiniert Elemente paarweise aus mehreren Streams.flatMap— wandelt einen Stream in einen anderen Stream um (häufig für Netzwerkanfragen verwendet).catch/retry— Fehlerbehandlung.
Auch in der Bibliothek
Event Bus und Observer-Pattern in PHP: Implementierung und Beispiele
Caching in Kotlin: Redis und andere Lösungen
Swagger/OpenAPI-Generierung für JavaScript (Node.js) — Werkzeuge und Bibliotheken