iOS: RxSwift + clean architecture

Raul Peña Alonso
Tiendeo Tech
Published in
3 min readMar 20, 2019

In a previous post we had the opportunity to define the architecture of our app conceptually. The purpose of this post is to get deep into implementation of key components of this architecture we’re using.

In this post we’ll talk about how we implement:

RxSwift + clean architecture

Our app uses ReactiveX swift version: RxSwift. RxSwift is a powerful tool to compose asynchronous operation and event/data streams. These streams make easy the communication between layers. That’s why we think that it fits perfectly to our architecture demands.

The way RxSwift streams through the different layers of our architecture is represented in this scheme:

Basically, Presenter execute a use case that returns an Observable. This Observable is created on data layer and passed by domain layer. Presenter subscribes to this Observable to fetch the result from the repository.

But, what is an Observable?

If we read the RxSwift’s Getting Started document we can understand what an Observable is:

Every Observable sequence is just a sequence. The key advantage for an Observable vs Swift's Sequence is that it can also receive elements asynchronously. This is the kernel of RxSwift.

Let’s get into implementation layer by layer:

Implementation

  • UI Layer

Presenter has a use case to execute. The method execute returns an Observable. Presenter subscribes to this Observable:

Notice that after the subscribe closure, we call disposed(by: disposeBag). This method adds the subscription to the disposeBag in order to cancel that subscription. Using [unowned self] or [weak self] inside of the closures and dispose(by:) method at the end will save your app from a memory leak. 😉

  • Domain layer

The use case has a method execute that invokes a CatalogRepository protocol method and returns an Observable created by that repository:

  • Data layer

Data repository implements CatalogRepository protocol defined in domain layer and has and array of data sources. Those data sources, in turn, implements CatalogDataSource protocol. Inside each method from data repository, it invokes a function from CatalogDataSource for each data source that it contains. To concatenate those invocations we use the Observable’s operation concat as follows:

Remote data source creates an Observable and execute the request using Alamofire. The response result will be sent to presenter by Observable onNext(), onCompleted() or onError() methods.

And that’s all! Connection through layers done! ✅

This could be a common case in everyone’s app, but RxSwift are a powerful tool, this is just the tip of the iceberg.

Let’s get deep into one of the things we use more in our projects:

Operators

There’re numerous operators in RxSwift: to create, to transform, to filter, to combine, … that can make your life easier. Here you can find a list. In case you need an operator and don’t know how to find it there is a decision tree of operators. There’re also a marble diagram to see how operators work: RxMarbles.

In this post, we’ve already seen concat operation, but we are going into detail about other operators we use the most.

  • zip

We use this operator to get the result of multiple Observables and operate with their results.

  • flatMap

This operator saved our lives. 🙏 We use this operator when we need to concatenate multiple Obsevables, but the result of the previous Observable will be needed for the execution of next Observable.

  • just / error

We use these operators to return an specific observable type as required. In the following example we use both.

  • from / filter / sorted / map / take / toArray

We use all these operators when we fetch data from Realm. In the following example we can see how powerful Observables’ operators are when combined. ✨

You can also create custom operators.

Hope you found this post interesting and useful for your projects. Any question or comment will be welcome!

Thanks and good luck!!!

Related articles

In the following posts we detail other key components from our architecture:

--

--