RxSwift to ReactiveSwift Cheatsheet

December 20, 2022 · View on GitHub

This is a Cheatsheet for RxSwift developers migrating to projects using ReactiveSwift.

Inspired by the RxSwift to Combine cheatsheet

Basics

RxSwiftReactiveSwift
Deployment TargetiOS 9.0+iOS 11.0+
Platforms supportediOS, macOS, tvOS, watchOS, LinuxiOS, macOS, tvOS, watchOS, Linux
SpecReactive Extensions (ReactiveX)Originally ReactiveX, with significant divergence
Framework ConsumptionThird-partyThird-party
Maintained byOpen-Source / CommunityOpen-Source / Community
UI BindingsRxCocoaReactiveCocoa

Core Components

RxSwiftReactiveSwiftNotes
AnyObserverSignal.ObserverIn practice, since there are no different Observer types, the AnyObserver concept is redundant in ReactiveSwift
BehaviorRelayProperty / MutablePropertySince MutableProperty can never have errors, we don't need a Relay specific version.
BehaviorSubjectProperty / MutableProperty
CompletableSignal / SignalProducerA Signal or SignalProducer where Value == Never can only complete or emit an error event
CompositeDisposableCompositeDisposable
ConnectableObservableType
DisposableDisposableIn ReactiveSwift you rarely have to keep hold of Disposables or manage their lifetime manually, it's mostly automatic.
DisposeBagCompositeDisposableThe concepte of a DisposeBag is not really needed in ReactiveSwift, see above.
Driver
MaybeTrivial to create using take(first: 1)
ObservableSignal / SignalProducerSignal is a "hot" observable, and SignalProducer is a "cold" observable that will only emit values once a subscription is started
ObserverSignal.Observer
PublishRelayCould be recreated easily in ReactiveSwift using the flatMapError operator on a Signal.pipe()
PublishSubjectSignal.pipe()There is no Subject type, but Signal.pipe() returns a tuple of (output: Signal, input: Signal.Observer) which you use to both observe and send values
ReplaySubjectCan be created using the replayLazily(upTo:) operator
ScheduledDisposable
SchedulerTypeScheduler
SerialDisposableSerialDisposable
SignalNot to be confused with ReactiveSwift Signal which is completely different
SingleCould easily be created as an initializer for SignalProducer
SubjectTypeSignal.pipe()There is no Subject type, but Signal.pipe() returns a tuple of (output: Signal, input: Signal.Observer) which you use to both observe and send values
TestSchedulerTestScheduler

Operators

RxSwiftReactiveSwiftNotes
amb()flatten(.race)
asObservable()Not required in ReactiveSwift, although Property.producer and Property.signal are similar
asObserver()
bind(to:)<~ operator (BindingTargets)
buffer(it used to exist, but was removed)
catchErrorflatMapError
catchErrorJustReturnEasy to create as flatMapError { _ in SignalProducer<Value, Never> (value: value) }
combineLatestcombineLatest
compactMapcompactMap
concatconcat / prefix
concatMap
createSignalProducer.init { }
debouncedebounce
debuglogEvents
deferredTrivial to create
delaydelay
delaySubscription
dematerializedematerialize
distinctUntilChangedskipRepeats
doon
elementAt
emptySignalProducer.empty
enumerated
errorSignalProducer.init(error:)
filterfilter
firsttake(first:)See also take(last:)
flatMapflatMap(.merge)
flatMapFirstflatMap(.throttle)
flatMapLatestflatMap(.latest)
from(optional:)Easy to create using .init(.value: Value?).skipNil()
groupBy
ifEmpty(default:)
ifEmpty(switchTo:)
ignoreElementsEasy to create
interval
justSignalProducer.init(value:)
mapmap
materializematerialize
mergemerge
merge(maxConcurrent:)
multicastreplayLazily(upTo:)
neverSignalProducer.never
observeOnobserve(on:)
ofSignalProducer.init(_ values:)
publish
range
reducereduce
refCountNot meaningful in ReactiveSwift
repeatElementrepeat
retry, retry(3)retry(upTo:)
retryWhen
samplesample(on:), sample(with:)
scanscan
sharereplayLazily(upTo:)
skipskip(first:)
skipUntilskip(until:)
skipWhileskip(while:)
startWithprefix
subscribestartWithValues / observeValues
subscribeOnstart(on:) / observe(on:)
takeLasttake(last:)
takeUntiltake(until:)
throttlethrottle
timeouttimeout
timerSignalProducer.timer
toArraycollect
window
withLatestFromcombineLatest
zipzip