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("Получено: \(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)")
    })
    .disposed(by: disposeBag)

state.accept("loading") // Выведет: Статус: 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 содержит все Business Logic в виде цепочек 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 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

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