Сравнение открытого фреймворка RxSwift и нативного Combine
Прежде всего, мы должны начать с объяснения того, что такое реактивное программирование. Это первый абзац определения в Википедии:
В вычислениях реактивное программирование — это декларативная парадигма программирования, связанная с потоками данных и распространением изменений. С помощью этой парадигмы можно с легкостью выражать статические (например, массивы) или динамические (например, генераторы событий) потоки данных, а также сообщать о существовании предполагаемой зависимости в связанной модели выполнения, что облегчает автоматическое распространение измененных данных. поток
Концепция проста: у нас есть отправители и получатели данных, а между ними мы применяем операторы для изменения, преобразования и работы с этими данными. Другой способ сказать, что он обрабатывает значения с течением времени.
Эти значения могут поступать из сетевых ответов или событий пользовательского интерфейса. Концепция реактивного программирования — это прямая замена блоков завершения или делегатов. Это приведет к более чистому и удобному в сопровождении конвейеру данных. при правильном использовании это может быть очень мощный подход к программированию.
В Swift два основных способа выполнения реактивного программирования — это фреймворки Combine и RxSwift.
Презентация комбината
Apple широко представила SwiftUI во время WWDC 2019, но они почти не сказали, что существует целая структура, которая его поддерживает: Combine. Это огромная новая структура, которая была слишком технической, чтобы попасть в заголовок, но она знаменует собой большое изменение в философии Apple, переход от декларативного к функционально-реактивному подходу. Вы можете использовать его, начиная с iOS 13, и, хотя он очень тесно связан со SwiftUI, вы все равно можете связать его с UIKit.
Некоторые типы Foundation раскрывают свои функциональные возможности через издателей, включая Timer
, NotificationCenter
и URLSession
. Combine также предоставляет встроенный издатель для любого свойства, совместимого с наблюдением за ключом и значением.
Не стесняйтесь проверять Документацию Apple о Combine для получения дополнительной информации.
Презентация RxSwift
RxSwift — это фреймворк с открытым исходным кодом. Вы можете использовать его, начиная с iOS 8. Это большое преимущество, так как вы можете безопасно начать интегрировать его в свой проект сейчас, в то время как вы можете подождать год или два, пока Combine будет поддерживать больше версий iOS.
Это очень популярный фреймворк, и у него большое сообщество, поэтому найти помощь и документацию совсем не сложно. Вы начинаете с проверки основного репозитория GitHub, где вы найдете всю их основную документацию.
Давайте сравним!
Об эмиттерах
Объединить: Publisher
– это протокол, определяющий требования к типу, чтобы он мог передавать последовательность значений во времени одному или нескольким подписчикам. Это похоже на то, что делает NotificationCenter
, за исключением того, что это, конечно, сделано лучше и читабельнее. Вы можете создать свой собственный, но Apple также предоставляет целый набор готовых издателей в своем enum.
let publisher = NotificationCenter.default .publisher(for: NSControl.textDidChangeNotification, object: filterField)
RxSwift: они называются Observable
. Это класс, который передает потоки (на самом деле не испускает) Event
, которые затем принимаются Observers
. Подробнее об этом позже.
let name: String = "Peter" let observable = Observable<String>.just(name)
О приемниках
Объединить: Subscriber
– это протокол, определяющий требования к типу, чтобы он мог получать входные данные от Publisher
.
let subscriber = NotificationCenter.default .publisher(for: NSControl.textDidChangeNotification, object: filterField) .sink(receiveCompletion: { print ($0) }, receiveValue: { print ($0) })
RxSwift: Observer
напрямую подписывается на Observable
. В отличие от NotificationCenter
, где разработчики обычно используют только одиночный экземпляр .default
, каждый наблюдаемый объект в Rx отличается. Кроме того, очень важно знать, что наблюдаемый объект не будет транслировать события или выполнять какую-либо работу, пока у него не появится подписчик.
let name: String = "Peter" let observable = Observable<String>.just(name) observable.subscribe { event in print(event) }
В целом, у вас много общих операторов с более или менее одинаковыми именами. Шай Мишали сделал эту очень удобную таблицу вам в помощь.
Обратное давление
Комбинируйте поддержку противодавления, но это не относится к RxSwift. В ReactiveX нетрудно попасть в ситуацию, когда Observable
передает элементы быстрее, чем оператор или наблюдатель может их использовать. Вы по-прежнему можете контролировать это с помощью холодных наблюдаемых, которые передают последовательность, когда ее наблюдатель считает это удобным, и с любой скоростью, которую желает наблюдатель, не нарушая целостность последовательности.
Тип ошибки
Для Combine требуется определенный тип ошибки, в то время как RxSwift работает с простым типом Error
. Со стороны Альянса это может показаться более сложной задачей, но я думаю, что это к лучшему. Управление ошибками имеет решающее значение, и «принуждение» к использованию вашего пользовательского типа Error
приведет к улучшению журналов ошибок.
Управление памятью
В RxSwift есть очень удобная система Dispose Bag. Все подписки на наблюдаемые объекты хранятся в одном уникальном объекте, что позволяет нам более эффективно управлять жизненным циклом этих подписок. При этом подписки также работают с ARC. Подписка всегда освобождается, когда она завершена или завершена из-за ошибки.
let disposeBag = DisposeBag()
let name: String = "Peter" let observable = Observable<String>.just(name) observable.subscribe { event in print(event) }.addDisposableTo(disposeBag)
Для объединения это называется Cancellable
. Все подписки управляются отдельно. Это немного больше усилий, но для получения большего контроля над нашим кодом и, возможно, улучшения производительности, поскольку под капотом DisposeBag
много операций.
private var cancellable: AnyCancellable? self.cancellable = subject .sink { value in print(value) }
Спектакли
Apple разработала Combine с учетом аспекта производительности. Цитируя инженера Apple: «Модели памяти RxSwift и Combine очень разные. Комбайн действительно создан для производительности». Он почти удваивает характеристики RxSwift, что позволяет Apple интегрировать Combine в высокопроизводительные требовательные платформы, такие как RealityKit.
Заключение
У вас есть веские аргументы с обеих сторон, чтобы использовать тот или иной фреймворк. В целом, используйте Combine, если вы хотите использовать что-то, изначально интегрированное в iOS, и если вам не нужно поддерживать версии iOS до iOS 13. Это также приведет к увеличению производительности.
RxSwift, с другой стороны, охватывает более широкий спектр версий iOS, а также имеет более широкое сообщество и больше руководств/примеров/контента.
Но важный вопрос: хотите ли вы перейти на реактивное программирование? Это полностью изменит ваше представление о потоке данных и архитектуре в пользу современного, более безопасного и менее подверженного ошибкам подхода к выбранной вами структуре.