RxSwift — co to jest, kluczowe pojęcia i programowanie reaktywne

Autor: IT Sectr Opublikowano: 2026-03-17 Czas czytania: 8 min

RxSwift to biblioteka programowania reaktywnego dla Swift, implementująca wzorzec Observable. Według danych ReactiveX, 2025, jest to najpopularniejsza implementacja Reactive Extensions dla ekosystemu Apple. Observable jest źródłem zdarzeń, a Observer subskrybuje je.

Najważniejsze

  • RxSwift — implementacja Reactive Extensions dla Swift z obsługą Observable, Subject i 300+ operatorów
  • Observable — źródło zdarzeń, które emituje wartości, błędy lub sygnał zakończenia
  • Subject — jednocześnie Observable i Observer, umożliwia ręczne wstawianie zdarzeń do strumienia
  • DisposeBag — mechanizm automatycznego zarządzania pamięcią, anulujący subskrypcje przy dealokacji
  • Schedulers — zarządzają wątkami wykonania, umożliwiając przełączanie między kolejkami main i background

Czym jest RxSwift?

RxSwift to biblioteka programowania reaktywnego dla języka Swift, przeniesiona z Reactive Extensions (Rx). Pozwala opisywać programy asynchroniczne i sterowane zdarzeniami poprzez Observable Sequence — sekwencję danych dostępnych w czasie. Deweloperzy iOS używają RxSwift do obsługi zapytań sieciowych, zdarzeń UI i danych strumieniowych bez zagnieżdżonych callback.

Observable i Observer

Podstawę RxSwift stanowią dwa kluczowe protokoły: ObservableType — źródło zdarzeń, które może emitować trzy typy sygnałów: .next(value), .error(error) i .completed. Observer subskrybuje Observable za pomocą metody subscribe i otrzymuje te zdarzenia. Taki model nazywa się Reactive Streams i gwarantuje, że żadne zdarzenie nie zostanie utracone przy prawidłowej subskrypcji.

Operatory transformacji

RxSwift udostępnia ponad 300 operatorów do pracy ze strumieniami: map przekształca każde zdarzenie, filter przepuszcza tylko pasujące, flatMap rozwija zagnieżdżone Observable w jeden strumień. Operatory łączy się w łańcuchy, tworząc deklaratywny pipeline przetwarzania danych bez efektów ubocznych.

Traits: Single, Completable, Maybe

Oprócz podstawowego Observable, RxSwift udostępnia wyspecjalizowane typy opakowujące. Single emituje dokładnie jedną wartość lub błąd — idealny do zapytań HTTP. Completable kończy się sukcesem lub błędem bez wartości — dla operacji zapisu. Maybe łączy oba scenariusze: może zakończyć się z wartością, bez wartości lub z błędem. Te Traits upraszczają semantykę i czynią kod samodokumentującym.

Jak działa programowanie reaktywne w RxSwift

Programowanie reaktywne w RxSwift opiera się na wzorcu Observer. ObservableSequence to odpowiednik Sequence z biblioteki standardowej, ale z asynchronicznym dostępem do elementów. Strumień zdarzeń przekazywany jest przez łańcuch operatorów, z których każdy zwraca nową ObservableSequence, nie mutując oryginalnej.

Łańcuchy operatorów

Operatory w RxSwift to czyste funkcje, przyjmujące jedną ObservableSequence i zwracające nową. Na przykład map tworzy nową sekwencję, stosując transformację do każdego elementu. Łącząc operatory, deweloper buduje pipeline, w którym dane przechodzą przez wszystkie etapy przetwarzania bez zmiennych pośrednich.

Schedulers i wątki wykonania

Schedulers to abstrakcja nad wątkami wykonania w RxSwift. Scheduler określa, na którym wątku będzie wykonywany kod: MainScheduler — wątek UI, SerialDispatchQueueScheduler — kolejka tła. Operatory subscribeOn i observeOn określają, gdzie wykonywana jest praca i gdzie przetwarzane są wyniki.

Główne komponenty RxSwift

RxSwift zawiera kilka podstawowych typów, z których każdy rozwiązuje swoje zadanie w reaktywnym pipeline. Single — Observable emitujący dokładnie jedną wartość lub błąd, wygodny do zapytań sieciowych. Completable kończy się sukcesem lub błędem bez wartości. Maybe łączy właściwości Single i Completable.

Subject i Relay

Subject to gorący Observable, który jednocześnie pełni rolę Observera. PublishSubject emituje tylko nowe zdarzenia subskrybentom, BehaviorSubject — ostatnie zdarzenie plus nowe. Relay to wariant Subject, który nie emituje .error ani .completed, gwarantując ciągłość strumienia. BehaviorRelay przechowuje bieżącą wartość i nadaje się do State-driven UI.

DisposeBag

DisposeBag to kolekcja Disposable, automatycznie anulująca wszystkie subskrypcje przy swojej dealokacji. W iOS DisposeBag jest zwykle dodawany do UIViewController lub UIView. Przy zamknięciu ekranu DisposeBag jest czyszczony — zapobiega to wyciekom pamięci i odwołaniom do nieistniejących elementów UI.

Przykłady kodu RxSwift

Poniżej pokazano przykład tworzenia Observable z tablicy danych z użyciem operatora map do przekształcania ciągów znaków:

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

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

W drugim przykładzie pokazano łączenie dwóch zapytań sieciowych za pomocą zip — operator czeka, aż oba Observable wyemitują wartość, i łączy wyniki w krotkę:

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)

Trzeci przykład pokazuje użycie BehaviorRelay do przechowywania stanu i automatycznej aktualizacji UI przy zmianach: każda zmiana state.accept() jest natychmiast transmitowana subskrybentom, co idealnie nadaje się do wzorców State w architekturze MVVM.

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

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

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

RxSwift a inne podejścia

RxSwift różni się od tradycyjnych metod asynchroniczności (Delegation, NotificationCenter, Callback) deklaratywnością i komponowalnością. W przeciwieństwie do Combine, RxSwift obsługuje iOS 9+ i ma więcej operatorów. Jednak Combine jest zintegrowany z Foundation i SwiftUI na poziomie języka, co daje mu przewagę w nowych projektach Apple.

Główna zaleta RxSwift nad GCD (Grand Central Dispatch) — możliwość łączenia i przekształcania strumieni danych na poziomie abstrakcji, a nie ręcznego zarządzania kolejkami. Jednocześnie RxSwift wymaga nauki koncepcji podejścia reaktywnego, co podnosi próg wejścia dla zespołu.

W praktyce RxSwift jest używany w dużych projektach, gdzie reaktywne łańcuchy łączą zdarzenia UI, logikę biznesową i komunikację sieciową w jeden pipeline. Na przykład w aplikacjach tradingowych strumienie notowań są przetwarzane przez RxSwift: ticki przychodzą z WebSocket, przechodzą filtrację, grupowanie według ram czasowych i wyświetlanie na wykresie w czasie rzeczywistym. Taki scenariusz jest trudny do zrealizowania przez Delegation lub NotificationCenter bez utraty czytelności.

Alternatywy dla RxSwift obejmują Combine (iOS 13+), AsyncSequence z Swift Concurrency (iOS 15+), a także biblioteki zewnętrzne ReactiveSwift bez powiązania z platformami Apple. Wybór zależy od minimalnej obsługiwanej wersji iOS i doświadczenia deweloperów. W nowych projektach iOS 15+ zespoły często wybierają AsyncSequence — nie wymaga instalacji bibliotek i używa natywnych konstrukcji języka Swift.

Wzorce architektoniczne z RxSwift zwykle podążają za MVVM lub Clean Architecture. ViewModel zawiera całą logikę biznesową w postaci łańcuchów Observable, View subskrybuje przekształcone dane. Wzorzec Input-Output dzieli zdarzenia wejściowe (tapnięcia, wprowadzanie tekstu) i stany wyjściowe (tekst przycisku, widoczność loadera). Takie podejście upraszcza testowanie: ViewModel jest testowany bez UI przez wirtualne Schedulery.

RxSwift nadaje się zarówno do małych projektów z kilkoma ekranami, jak i do dużych aplikacji enterprise z dziesiątkami modułów. W dużych projektach reaktywne łańcuchy przenikają całą architekturę: od obserwacji UserDefaults przez RxProperty po zapytania sieciowe przez Moya (nakładka RxSwift na Alamofire). Każdy moduł jest izolowany i komunikuje się przez reaktywne interfejsy, co upraszcza wymianę implementacji bez zmiany subskrybentów. Przy prawidłowej architekturze z RxSwift zmniejsza się ilość kodu w porównaniu z klasycznymi podejściami, ponieważ nie trzeba pisać boilerplate dla KVO, Target-Action czy NotificationCenter.

RxSwift jest aktywnie używany w projektach z RxDataSources — biblioteką do reaktywnej pracy z UITableView i UICollectionView. RxDataSources automatycznie oblicza różnicę między starym a nowym zestawem komórek i stosuje animowane zmiany. To uwalnia dewelopera od ręcznej pracy z beginUpdates/endUpdates i eliminuje crash przy niezgodności danych.

Do debugowania łańcuchów RxSwift istnieje operator debug() — loguje wszystkie zdarzenia: subscribe, next, error, completed, dispose. To niezbędne narzędzie przy tworzeniu złożonych reaktywnych pipeline. debug(String) przyjmuje identyfikator wyświetlany w logach. Do profilowania pamięci RxSwift.Resources.total pokazuje całkowitą liczbę aktywnych Observable i Disposable w aplikacji — pomaga wykryć wycieki, gdy DisposeBag nie jest wyczyszczony lub retain cycle utrzymuje subskrypcję. Dodatkowy operator takeUntil(self.rx.deallocated) automatycznie anuluje subskrypcję przy dealokacji obiektu — to kolejna warstwa ochrony przed wyciekami.

Najlepsze praktyki RxSwift

Podczas pisania kodu RxSwift ważne jest przestrzeganie zasady jeden Observable na subskrypcję: każdy ViewController nie powinien tworzyć więcej niż jednej subskrypcji do jednego Observable — zmniejsza to ryzyko race condition. Do memoizacji Observable używa się operatora share(), który zmienia zimny Observable w gorący z replay-buforem rozmiaru 1. Podczas pracy ze współdzielonymi zasobami używaj connect() do zarządzania rozpoczęciem emisji — gwarantuje to, że wszyscy subskrybenci połączą się przed pierwszym zdarzeniem.

Testowanie kodu RxSwift wykonuje się przez TestScheduler — wirtualny Scheduler, który umożliwia zarządzanie czasem. testScheduler.createHotObservable(values) tworzy Observable z predefiniowaną sekwencją zdarzeń według wirtualnego czasu. testScheduler.start() uruchamia przetwarzanie. TestScheduler pozwala sprawdzać, w jakiej kolejności i na jakim wirtualnym znaczniku czasu występują zdarzenia, bez rzeczywistych opóźnień, co czyni testy szybkimi i deterministycznymi.

Często zadawane pytania

Jaka jest różnica między Observable a Subject w RxSwift?

Observable to zimne źródło: nie emituje zdarzeń do momentu subskrypcji. Subject jest gorący: emituje zdarzenia niezależnie od subskrybentów i umożliwia ręczne wstawianie wartości przez onNext. PublishSubject przekazuje tylko nowe zdarzenia, BehaviorSubject — ostatnie plus nowe.

Jak DisposeBag zapobiega wyciekom pamięci w RxSwift?

DisposeBag przechowuje wszystkie Disposable subskrypcje. Gdy DisposeBag jest dealokowany (na przykład przy zamknięciu ViewController), wszystkie przechowywane subskrypcje są automatycznie anulowane. Gwarantuje to, że Observable nie wyśle już zdarzenia do zniszczonego obiektu UI.

Co wybrać: RxSwift czy Combine w nowym projekcie iOS?

Jeśli minimalna wersja iOS 13+ i zespół zna SwiftUI — wybierz Combine. Jeśli projekt obsługuje iOS 12 i niżej lub wymaga większego zestawu operatorów — RxSwift. Combine zapewnia lepszą integrację z Foundation (URLSession, Timer, NotificationCenter).

Jak działają Schedulers w RxSwift?

Schedulers abstrahują wątki wykonania. subscribeOn wskazuje, na którym Schedulerze wykonywana jest subskrypcja (zwykle background). observeOn określa, na którym Schedulerze odbierane są zdarzenia (częściej MainScheduler dla aktualizacji UI). SerialDispatchQueueScheduler działa przez GCD.

Czy można używać RxSwift z SwiftUI?

Tak, RxSwift można zintegrować ze SwiftUI przez ObservableObject. Użyj BehaviorRelay jako właściwości @Published: subskrypcja Relay transmitowana zmiany do Combine, a SwiftUI przerysowuje View przez @ObservedObject. To popularny wzorzec migracji z UIKit na SwiftUI.

Podsumowanie

  • RxSwift — biblioteka programowania reaktywnego oparta na Reactive Extensions i wzorcu Observable
  • Observable emituje trzy typy sygnałów: .next, .error i .completed
  • Subject (PublishSubject, BehaviorSubject) łączy Observable i Observer dla gorących strumieni
  • DisposeBag zarządza cyklem życia subskrypcji i zapobiega wyciekom pamięci
  • Operatory (map, filter, flatMap, zip) umożliwiają budowanie deklaratywnych łańcuchów przetwarzania
  • Schedulers przełączają wykonanie między kolejkami tła a wątkiem UI
  • W nowych projektach na iOS 13+ rozważ Combine jako wbudowaną alternatywę

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również