In today’s article I’d like to give an introduction to Combine and show its main differences with RxSwift , and probably the best way to start is by showing Apple’s definition of Combine:
A unified, declarative API for processing values overtime
I’m sure it sounds familiar; that’s because, as we’ve said earlier, in this article we’ll talk about some of the similar features and differences between Combine
and RxSwift
, starting with Combine and its main features.
Combine vs RxSwift: Introduction to Combine
We’ll start by highlighting Combine’s three main attributes
- Generic.
- Type safe.
- Composition first.
Apple tells us in their Combine keynote that the main concepts are simple and easy to understand, but once combined they allow for more complex and interesting stuff to be done.
Within Combine we’ll find:
- Publishers
- Subscribers
- Operators
Publishers
Publishers are the most declarative part of Combine’s API. They define how values and errors are produced.
They’re Value type , in Swift, Structs.
Publishers allow the subscription of Subscribers, in turn letting us receive values once they’re emitted.
protocol Publishers {
associatedtype Output
associatedtype Failure: Error
func subscribe<S: Subscriber>(_ subscriber: S)
where S.input == Output, S.Failure == Failure
}
Subscribers
Subscribers are the other side of the publishers coin. They receive values through the stream, and since these can mutate they are Reference types , like classes.
protocol Subscriber {
associatedtype Input
associatedtype Failure: Error
func receive(subscription: Subscription)
func receive(_ input: Input) -> Subscribers.Demand
func receive(completion: Subscribers.Completion<Failure>)
}
This reminds me of something…
Looking at these basic Combine concepts we can deduce that it is very similar to other existing reactive programming frameworks like RxSwift or ReactiveCocoa. For now, let’s focus on how it compares to RxSwift.
If you’re familiar with RxSwift you’ll notice that Publishers
are basically Observables
and Subscribers
are Observers
; they have different names but work the same way. A Publisher exposes values that can change and a Subscriber
“subscribes” so it can receive all these changes.
Combine vs RxSwift: Differences
Current compatibility
First off, Combine does not offer backward compatibility, that is, it’s not available for systems older than iOS 13 / macOS Catalina, since it needs the new runtime process in order to work. There are no future plans to introduce this backward compatibility.
RxSwift works with iOS 8 and above.
Error management
Looking at the specification for the Observable
protocol we’ll spot the first differences.
In Combine, every Publisher
needs to specify an error type, while in RxSwift, Observables
don’t use an error type, instead they can throw
any type of error at any given moment. This makes RxSwift’s Observables
easier to use, since you don’t have to think about the types of errors that should be launched. On the other hand, this means you’ll have to be careful when managing errors by yourself, since the compiler won’t help you if you missed one, something that wouldn’t happen with Combine since it’s way more strict.
With Combine, if your stream doesn’t throw errors of any kind you can mark it with the type Never
.
While this explicit specification of error types can be seen as an extra layer of security, it also adds some complications to the code. Meanwhile, you can get something similar with RxSwift using the Result
type, which adds an additional error type but your stream wouldn’t stop after throwing an error, or using a specific stream for error management.
There’s another difference regarding error management: Combine separates functions as throwing
or non-throwing
. For example, there’re operators that have an error-throwing version and the non-throwing
one.
Performance
Performance wise, and while it’s undeniable that RxSwift is a properly optimized framework, Combine has been built by Apple’s engineers with a 100% focus on performance.
As we can see on Flawless iOS blog, they did a comparison executing two code blocks doing the same work, one with Combine and the other with RxSwift, and we can observe that Combine’s time performance is the winner.
One of the main reasons for this improvement is because RxSwift uses Swift as its main language and thus needs to do a lot of sinks
on the frameworks’ lower layers, affecting its performance. On the other hand, Combine is a Close Source project, and might not have necessarily been developed using Swift (but can expose a public Swift interface). Apple can use a lot of performance optimizations not available to developers outside of the company.
Operators
Combine and RxSwift have a lot of operators doing the same or a very similar job, but with a different naming.
Thankfully, the chart created by Shai Mishali can help us link all these operators with different names.
Open source
An important element that we’ve mentioned before is that Combine is not an open source project, something pretty logic if we take into account that the rest of Apple frameworks aren’t either. It’s feasible that Combine uses system features only available to Apple developers, but even if it was open source, Apple would still have a bigger advantage when tackling potential problems related to their core.
DisposeBag
You’re probably already familiar with RxSwift memory management pattern, DisposeBag. Instead of storing each subscription separately and ending them when the controller or class deinitializes, we simply write .disposed(by: disposeBag)
and the framework will detect the deinit
and get rid of all those Rx dependencies.
Combine doesn’t have anything similar to DisposeBag
.
UI Framework
Inside a reactive framework we need some way to link the reactive flows to the view, and vice versa. RxSwift’s solution is RxCocoa
.
Combine doesn’t have a specific framework to do these binds, instead we can use the assign
method to link a stream
to a key path and a view property.
publisher.assign(to: \.text, on: label)
Combine (still) doesn’t have a way to obtain a stream from a UI component in the same way we can with RxCocoa
.
Conclusion
Mi opinion, leaving aside the differences between these frameworks, is that the creation of more reactive programming tools is very positive for Swift. It’s possible that the Combine’s emergence will give a popularity push to RxSwift, and during the next years, as Combine keeps maturing, at some point it might be worth it to jump straight into Apple’s framework. For the moment, and seeing how it has no backward compatibility, we can still enjoy RxSwift.
The post Combine vs RxSwift: Introduction to Combine & differences appeared first on Apiumhub.
Top comments (0)