RxSwift — що це, ключові поняття та реактивне програмування

Автор: IT Sectr Опубліковано: 2026-03-17 Час читання: 8 хв

RxSwift — це бібліотека реактивного програмування для Swift, яка реалізує патерн Observable. За даними ReactiveX, 2025, це найпопулярніша реалізація Reactive Extensions для екосистеми Apple. Observable виступає джерелом подій, а Observer підписується на їх отримання.

Головне

  • RxSwift — реалізація Reactive Extensions для Swift з підтримкою Observable, Subject та 300+ операторів
  • Observable — джерело подій, яке емітить значення, помилки або сигнал завершення
  • Subject — одночасно Observable і Observer, дозволяє вручну вставляти події в потік
  • DisposeBag — механізм автоматичного керування пам'яттю, що відписує підписки при деалокації
  • Schedulers — керують потоками виконання, дозволяючи перемикатися між main та background чергами

Що таке RxSwift?

RxSwift — це бібліотека реактивного програмування для мови Swift, портована з Reactive Extensions (Rx). Вона дозволяє описувати асинхронні та подійно-орієнтовані програми через Observable Sequence — послідовність даних, доступних у часі. Розробники iOS застосовують RxSwift для обробки мережевих запитів, UI-подій та потокових даних без вкладених callback.

Observable та Observer

Основу RxSwift складають два ключових протоколи: ObservableType — джерело подій, яке може емітити три типи сигналів: .next(value), .error(error) та .completed. Observer підписується на Observable через метод subscribe та отримує ці події. Така модель називається Reactive Streams і гарантує, що жодна подія не буде втрачена при правильній підписці.

Оператори трансформації

RxSwift надає більше 300 операторів для роботи з потоками: map перетворює кожну подію, filter пропускає тільки відповідні, flatMap розгортає вкладені Observable в єдиний потік. Оператори об'єднуються в ланцюжки, створюючи декларативний пайплайн обробки даних без побічних ефектів.

Traits: Single, Completable, Maybe

Крім базового Observable, RxSwift надає спеціалізовані типи-обгортки. Single емітить рівно одне значення або помилку — ідеальний для HTTP-запитів. Completable завершується успіхом або помилкою без значення — для операцій запису. Maybe об'єднує обидва сценарії: може завершитися зі значенням, без значення або з помилкою. Ці Traits спрощують семантику та роблять код самодокументованим.

Як працює реактивне програмування в RxSwift

Реактивне програмування в RxSwift будується на паттерні Observer. ObservableSequence — це аналог Sequence зі стандартної бібліотеки, але з асинхронним доступом до елементів. Потік подій передається по ланцюжку операторів, кожен з яких повертає нову ObservableSequence, не мутуючи вихідну.

Ланцюжки операторів

Оператори в RxSwift — це чисті функції, що приймають одну ObservableSequence та повертають нову. Наприклад, map створює нову послідовність, застосовуючи трансформацію до кожного елемента. Комбінуючи оператори, розробник будує пайплайн, де дані проходять всі стадії обробки без проміжних змінних.

Schedulers та потоки виконання

Schedulers — це абстракція над потоками виконання в RxSwift. Scheduler визначає, на якому потоці буде виконуватися код: MainScheduler — UI-потік, SerialDispatchQueueScheduler — фонова черга. Оператори subscribeOn та observeOn задають, де виконується робота та де обробляються результати відповідно.

Основні компоненти RxSwift

RxSwift включає кілька базових типів, кожен з яких вирішує своє завдання в реактивному пайплайні. Single — Observable, який емітить рівно одне значення або помилку, зручний для мережевих запитів. Completable завершується успіхом або помилкою без значення. Maybe поєднує властивості Single та Completable.

Subject та Relay

Subject — це гарячий Observable, який одночасно виступає Observer. PublishSubject емітить тільки нові події підписникам, BehaviorSubject — останню подію плюс нові. Relay — це варіант Subject, який не емітить .error або .completed, гарантуючи безперервність потоку. BehaviorRelay зберігає поточне значення та підходить для State-driven UI.

DisposeBag

DisposeBag — це колекція Disposable, яка автоматично відписує всі підписки при своєму деалоку. В iOS DisposeBag зазвичай додається в UIViewController або UIView. При закритті екрану DisposeBag очищається — це запобігає витокам пам'яті та зверненню до неіснуючих елементів UI.

Приклади коду RxSwift

Нижче показано приклад створення Observable з масиву даних з використанням оператора map для перетворення рядків:

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

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

У другому прикладі демонструється об'єднання двох мережевих запитів за допомогою zip — оператор чекає, поки обидва Observable емітять значення, та об'єднує результати в кортеж:

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)

Третій приклад показує використання BehaviorRelay для зберігання стану та автоматичного оновлення UI при змінах: кожна зміна state.accept() негайно транслюється підписникам, що ідеально підходить для State-патернів в MVVM архітектурі.

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

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

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

RxSwift vs інші підходи

RxSwift відрізняється від традиційних методів асинхронності (Delegation, NotificationCenter, Callback) декларативністю та композиційністю. На відміну від Combine, RxSwift підтримує iOS 9+ і має більше операторів. Однак Combine інтегрований в Foundation та SwiftUI на рівні мови, що дає йому перевагу в нових проектах Apple.

Основна перевага RxSwift перед GCD (Grand Central Dispatch) — можливість комбінувати та трансформувати потоки даних на рівні абстракцій, а не керувати чергами вручну. При цьому RxSwift вимагає вивчення концепцій реактивного підходу, що збільшує поріг входу для команди.

На практиці RxSwift використовується у великих проектах, де реактивні ланцюжки пов'язують UI-події, бізнес-логіку та мережеву взаємодію в єдиному пайплайні. Наприклад, у додатках для трейдингу потоки котирувань обробляються через RxSwift: тики приходять з WebSocket, проходять фільтрацію, групуються по таймфрейму та відображаються на графіку в реальному часі. Такий сценарій складно реалізувати через Delegation або NotificationCenter без втрати читабельності.

Альтернативи RxSwift включають Combine (iOS 13+), AsyncSequence з Swift Concurrency (iOS 15+), а також сторонні бібліотеки ReactiveSwift без прив'язки до платформ Apple. Вибір залежить від мінімальної підтримуваної версії iOS та досвіду розробників. Для нових проектів iOS 15+ команди часто обирають AsyncSequence — він не вимагає встановлення бібліотек і використовує нативні конструкції мови Swift.

Архітектурні паттерни з RxSwift зазвичай слідують MVVM або Clean Architecture. ViewModel містить всю бізнес-логіку у вигляді ланцюжків Observable, View підписується на трансформовані дані. Input-Output паттерн розділяє вхідні події (тапи, введення тексту) та вихідні стани (текст кнопки, видимість лоадера). Такий підхід спрощує тестування: ViewModel тестується без UI через віртуальні Schedulers.

RxSwift підходить як для малих проектів з парою екранів, так і для великих enterprise-додатків з десятками модулів. У великих проектах реактивні ланцюжки пронизують всю архітектуру: від UserDefaults спостереження через RxProperty до мережевих запитів через Moya (RxSwift-обгортка над Alamofire). Кожен модуль ізольований і спілкується через реактивні інтерфейси, що спрощує заміну реалізації без зміни підписників. При правильній архітектурі з RxSwift скорочується кількість коду порівняно з класичними підходами, оскільки не потрібно писати boilerplate для KVO, Target-Action або NotificationCenter.

RxSwift активно використовується в проектах з RxDataSources — бібліотекою для реактивної роботи з UITableView та UICollectionView. RxDataSources автоматично обчислює різницю між старим та новим набором комірок та застосовує анімовані зміни. Це позбавляє розробника від ручної роботи з beginUpdates/endUpdates та виключає crash при невідповідності даних.

Для налагодження ланцюжків RxSwift існує оператор debug() — він логує всі події: subscribe, next, error, completed, dispose. Це незамінний інструмент при розробці складних реактивних пайплайнів. debug(String) приймає ідентифікатор, який відображається в логах. Для профілювання пам'яті RxSwift.Resources.total показує загальну кількість активних Observable та Disposable в додатку — допомагає виявити витоки, коли DisposeBag не очищений або retain cycle утримує підписку. Додатковий оператор takeUntil(self.rx.deallocated) автоматично скасовує підписку при деалокації об'єкта — це ще один шар захисту від витоків.

Найкращі практики RxSwift

При написанні RxSwift коду важливо дотримуватися принципу єдиного Observable на підписку: кожен ViewController не повинен створювати більше одного Subscription до одного Observable — це знижує ризик race condition. Для мемоізації Observable використовується оператор share(), який робить холодний Observable гарячим з replay-буфером розміром 1. При роботі зі спільними ресурсами використовуйте connect() для керування початком емісії — це гарантує, що всі підписники підключаться до першої події.

Тестування RxSwift коду виконується через TestScheduler — віртуальний Scheduler, який дозволяє керувати часом. testScheduler.createHotObservable(values) створює Observable з попередньо визначеною послідовністю подій за віртуальним часом. testScheduler.start() запускає обробку. TestScheduler дає можливість перевіряти, в якому порядку та на якому віртуальному таймстемпі відбуваються події, без реальних затримок, що робить тести швидкими та детермінованими.

Поширені запитання

В чому різниця між Observable та Subject в RxSwift?

Observable — це холодне джерело: він не емітить події до підписки. Subject — гарячий: емітить події незалежно від підписників і дозволяє вручну вставляти значення через onNext. PublishSubject передає тільки нові події, BehaviorSubject — останню плюс нові.

Як DisposeBag запобігає витокам пам'яті в RxSwift?

DisposeBag зберігає всі Disposable підписки. Коли DisposeBag деалокується (наприклад, при закритті ViewController), всі збережені підписки автоматично скасовуються. Це гарантує, що Observable більше не надішле подію вже знищеному об'єкту UI.

Що вибрати: RxSwift чи Combine в новому iOS проекті?

Якщо мінімальна версія iOS 13+ і команда знає SwiftUI — вибирайте Combine. Якщо проект підтримує iOS 12 і нижче або вимагає більшого набору операторів — RxSwift. Combine дає кращу інтеграцію з Foundation (URLSession, Timer, NotificationCenter).

Як працюють Schedulers в RxSwift?

Schedulers абстрагують потоки виконання. subscribeOn вказує, на якому Scheduler виконується підписка (зазвичай background). observeOn визначає, на якому Scheduler приймаються події (найчастіше MainScheduler для UI-оновлень). SerialDispatchQueueScheduler працює через GCD.

Чи можна використовувати RxSwift з SwiftUI?

Так, RxSwift можна інтегрувати зі SwiftUI через ObservableObject. Використовуйте BehaviorRelay як @Published-властивості: підписка на Relay транслює зміни в Combine, а SwiftUI перемальовує View через @ObservedObject. Це популярний патерн міграції з UIKit на SwiftUI.

Підсумки

  • RxSwift — бібліотека реактивного програмування, заснована на Reactive Extensions та паттерні Observable
  • Observable емітить три типи сигналів: .next, .error та .completed
  • Subject (PublishSubject, BehaviorSubject) поєднує Observable та Observer для гарячих потоків
  • DisposeBag керує життєвим циклом підписок та запобігає витокам пам'яті
  • Оператори (map, filter, flatMap, zip) дозволяють будувати декларативні ланцюжки обробки
  • Schedulers перемикають виконання між фоновими чергами та UI-потоком
  • Для нової розробки на iOS 13+ розгляньте Combine як вбудовану альтернативу

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також