Logo for tanaschita.com

Introduction to Combine for iOS developers with RxSwift experience

How to start using Combine for reactive programming

updated on 08 Apr 2024 · 4 min read

If you are already exprerienced with RxSwift, switching to Combine will mostly be a matter of learning new namings for similar concepts.

Let's directly jump in.

Sponsorship logo
Preparing for a technical iOS job interview - updated for iOS 18
Check out my book on preparing for a technical iOS job interview with over 200 questions & answers. Test your knowledge on iOS topics such as Swift, SwiftUI, Combine, HTTP Networking, Authentication, SwiftData & Core Data, Concurrency with async/await, Security, Automated Testing, Machine Learning and more.
LEARN MORE

Publisher & Subscriber

A Publisher is what in RxSwift is an Observable. A publisher defines how values are produced and allows registration of a subscriber.

A Subscriber is what in RxSwift is an Observer. A subscriber receives values from the publisher after subscribing.

Let's remind how to create and subscribe to an Observable in RxSwift first:

let observable = Observable.from([1, 2, 3, 4])
observable.subscribe(onNext: { value in
print(value)
}, onCompleted: {
print("completed")
})

And here how it looks to create and register to a Publisher in Combine:

let publisher = Publishers.Sequence<[Int], Error>(sequence: [1, 2, 3, 4])
publisher.sink(receiveCompletion: { _ in
print("completed")
}) { value in
print(value)
}

Both examples produce the same output:

1
2
3
4
completed

SubjectType

A SubjectType is what in RxSwift is a Subject, so the name is not that different in this case. Only the subtypes of a subject were named differently.

There are two kinds of a subject type in Combine: PassthroughSubject and CurrentValueSubject.

A PassthroughSubject is what in RxSwift is a PublishSubject. If you subscribe to it you will get all events that happen after you subscribed.

A CurrentValueSubject is what in RxSwift is a BehaviourSubject. It behaves like a PassthroughSubject but it also will send it's most recent element to new subscribers.

In RxSwift, creating a subject and sending values to the observer might look as follows:

let subject = PublishSubject<String>()
subject.asObservable().subscribe(onNext: { value in
print(value)
})
subject.onNext("Yes")
subject.onNext("Ve")
subject.onNext("gan")

The equivalent in Combine:

let subject = PassthroughSubject<String, Never>()
subject.eraseToAnyPublisher().sink { value in
print(value)
}
subject.send("Yes")
subject.send("Ve")
subject.send("gan")

Both examples produce the same output:

Yes
Ve
gan

If you like going deeper, you can find a good comparison of available RxSwift und Combine components here.

Operators

Many operators like map, flatMap, reduce etc. that are available in RxSwift are also available in Combine. Using Combine operators is just like using RxSwift operators.

So it should feel really familiar to see Combine operators in action:

Publishers.Sequence(sequence: [1, 2, 2, 3, 3, 4, 7])
.map { $0 * 2 }
.filter { $0.isMultiple(of: 2) }
.dropFirst(3)
.removeDuplicates()
.sink { value in
print(value)
}

This code produces the following output:

6
8
14

A full comparison list of RxSwift und Combine operators is available here.

Error Handling

A notable difference between RxSwift’s Observable and Combine’s Publisher is the error handling. In RxSwift, we work with the general Error type whereas in Combine we can use any kind of custom error:

let publisher = Publishers.Sequence<[Int], SomeCustomError>(sequence: [1, 2])

If a subject can never fail, Combine provides the Never type:

let subject = PassthroughSubject<String, Never>()

Memory Management

To deal with ARC and memory management, RxSwift provides a DisposeBag. In Combine, we can use a collection of AnyCancellables.

Here is an example of how a DisposeBag is typically used in RxSwift:

let disposeBag = DisposeBag()
let subject = PublishSubject<String>()
subject.asObservable().subscribe(onNext: { value in
print(value)
}).disposed(by: disposeBag)

And here is the equivalent example in Combine:

var cancellables = Set<AnyCancellable>()
let subject = PassthroughSubject<String, Never>()
subject.eraseToAnyPublisher().sink { value in
print(value)
}.store(in: &cancellables)

Performance

I didn't compare the performance of RxSwift and Combine myself but there are some great articles about it. They all agree that Combine is clearly faster than RxSwift.

If you are interested in more specifics, you can find some performance tests and its results here. The tests compare the performance of the most commonly used components and operators in RxSwift and Combine.

Sponsorship logo
Preparing for a technical iOS job interview - updated for iOS 18
Check out my book on preparing for a technical iOS job interview with over 200 questions & answers. Test your knowledge on iOS topics such as Swift, SwiftUI, Combine, HTTP Networking, Authentication, SwiftData & Core Data, Concurrency with async/await, Security, Automated Testing, Machine Learning and more.
LEARN MORE

Newsletter

Image of a reading marmot
Subscribe

Like to support my work?

Say hi

Related tags

Articles with related topics

combine

reactive programming

swift

Quick guide on Combine essentials in Swift

Learn basic Combine concepts and terms.

20 May 2024 · 10 min read

Latest articles and tips

© 2024 tanaschita.com

Privacy policy

Impressum