RxSwift — это библиотека реактивного программирования для Swift, реализующая паттерн Observable. По данным ReactiveX, 2025, это самая популярная реализация Reactive Extensions для экосистемы Apple. Observable выступает источником событий, а Observer подписывается на их получение.
Главное
RxSwift — это библиотека реактивного программирования для языка Swift, портированная с Reactive Extensions (Rx). Она позволяет описывать асинхронные и событийно-ориентированные программы через Observable Sequence — последовательность данных, доступных во времени. Разработчики iOS применяют RxSwift для обработки сетевых запросов, UI-событий и потоковых данных без вложенных callback.
Основу RxSwift составляют два ключевых протокола: ObservableType — источник событий, который может эмитить три типа сигналов: .next(value), .error(error) и .completed. Observer подписывается на Observable через метод subscribe и получает эти события. Такая модель называется Reactive Streams и гарантирует, что ни одно событие не будет потеряно при правильной подписке.
RxSwift предоставляет более 300 операторов для работы с потоками: map преобразует каждое событие, filter пропускает только подходящие, flatMap разворачивает вложенные Observable в единый поток. Операторы объединяются в цепочки, создавая декларативный пайплайн обработки данных без побочных эффектов.
Кроме базового Observable, RxSwift предоставляет специализированные типы-обёртки. Single эмитит ровно одно значение или ошибку — идеален для HTTP-запросов. Completable завершается успехом или ошибкой без значения — для операций записи. Maybe объединяет оба сценария: может завершиться со значением, без значения или с ошибкой. Эти Traits упрощают семантику и делают код самодокументируемым.
Реактивное программирование в RxSwift строится на паттерне Observer. ObservableSequence — это аналог Sequence из стандартной библиотеки, но с асинхронным доступом к элементам. Поток событий передаётся по цепочке операторов, каждый из которых возвращает новую ObservableSequence, не мутируя исходную.
Операторы в RxSwift — это чистые функции, принимающие одну ObservableSequence и возвращающие новую. Например, map создаёт новую последовательность, применяя трансформацию к каждому элементу. Комбинируя операторы, разработчик строит пайплайн, где данные проходят все стадии обработки без промежуточных переменных.
Schedulers — это абстракция над потоками выполнения в RxSwift. Scheduler определяет, на каком потоке будет исполняться код: MainScheduler — UI-поток, SerialDispatchQueueScheduler — фоновая очередь. Операторы subscribeOn и observeOn задают, где выполняется работа и где обрабатываются результаты соответственно.
RxSwift включает несколько базовых типов, каждый из которых решает свою задачу в реактивном пайплайне. Single — Observable, который эмитит ровно одно значение или ошибку, удобен для сетевых запросов. Completable завершается успехом или ошибкой без значения. Maybe совмещает свойства Single и Completable.
Subject — это горячий Observable, который одновременно выступает Observer. PublishSubject эмитит только новые события подписчикам, BehaviorSubject — последнее событие плюс новые. Relay — это вариант Subject, который не эмитит .error или .completed, гарантируя непрерывность потока. BehaviorRelay хранит текущее значение и подходит для State-driven UI.
DisposeBag — это коллекция Disposable, автоматически отписывающая все подписки при своём деаллоке. В iOS DisposeBag обычно добавляется в UIViewController или UIView. При закртии экрана DisposeBag очищается — это предотвращает утечки памяти и обращение к несуществующим элементам UI.
Ниже показан пример создания Observable из массива данных с использованием оператора map для преобразования строк:
let observable = Observable.of("Swift", "RxSwift", "Reactive")
observable
.map { $0.uppercased() }
.subscribe(onNext: { value in
print("Получено: \(value)")
})
.disposed(by: disposeBag)
Во втором примере демонстрируется объединение двух сетевых запросов с помощью zip — оператор ждёт, пока оба Observable эмитят значение, и объединяет результаты в кортеж:
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 архитектуре.
let state = BehaviorRelay(value: "idle")
state
.subscribe(onNext: { status in
print("Статус: \(status)")
})
.disposed(by: disposeBag)
state.accept("loading") // Выведет: Статус: loading
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 кода важно соблюдать принцип единого Observable на подписку: каждый ViewController не должен создавать более одного Subscription к одному Observable — это снижает риск race condition. Для мемоизации Observable используется оператор share(), который делает холодный Observable горячим с replay-буфером размером 1. При работе с разделяемыми ресурсами используйте connect() для управления началом эмиссии — это гарантирует, что все подписчики подключатся до первого события.
Тестирование RxSwift кода выполняется через TestScheduler — виртуальный Scheduler, который позволяет управлять временем. testScheduler.createHotObservable(values) создаёт Observable с предопределённой последовательностью событий по виртуальному времени. testScheduler.start() запускает обработку. TestScheduler даёт возможность проверять, в каком порядке и на каком виртуальном таймстемпе происходят события, без реальных задержек, что делает тесты быстрыми и детерминированными.
Часто задаваемые вопросы
Observable — это холодный источник: он не эмитит события до подписки. Subject — горячий: эмитит события независимо от подписчиков и позволяет вручную вставлять значения через onNext. PublishSubject передаёт только новые события, BehaviorSubject — последнее плюс новые.
DisposeBag хранит все Disposable подписки. Когда DisposeBag деаллоцируется (например, при закртии ViewController), все хранящиеся подписки автоматически отменяются. Это гарантирует, что Observable больше не отправит событие уже уничтоженному объекту UI.
Если минимальная версия iOS 13+ и команда знает SwiftUI — выбирайте Combine. Если проект поддерживает iOS 12 и ниже или требует большего набора операторов — RxSwift. Combine даёт лучшую интеграцию с Foundation (URLSession, Timer, NotificationCenter).
Schedulers абстрагируют потоки выполнения. subscribeOn указывает, на каком Scheduler выполняется подписка (обычно background). observeOn определяет, на каком Scheduler принимаются события (чаще MainScheduler для UI-обновлений). SerialDispatchQueueScheduler работает через GCD.
Да, RxSwift можно интегрировать со SwiftUI через ObservableObject. Используйте BehaviorRelay как @Published-свойства: подписка на Relay транслирует изменения в Combine, а SwiftUI перерисовывает View через @ObservedObject. Это популярный паттерн миграции с UIKit на SwiftUI.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также