Dmitriy Petrov

Bring tables alive with RxDataSources. RxSwift part 1

Working with iOS I've always been confused about a big amount of delegates for tables creating and their complexity. As I've started to use RxSwift, I met its component - RxDataSources. Now I can say that work with tables has never been easier.
Dmitriy Petrov
iOS Developer
RxDataSources
Imagine that you have to make a table that will have some sections and each section can have different cell types. It's sure, everybody knows that feeling of routine while tables or collections creating. A lot of boilerplate code with no possibility to reduce it.
Imagine that you have to make a table that will have some sections and each section can have different cell types. It's sure, everybody knows that feeling of routine while tables or collections creating. A lot of boilerplate code with no possibility to reduce it.
RxSwift allows to make the problem easier to solve with DataSource wrapping into Observable and binding it to the table or collection.
But there are some cases when it's not enough. It's when you need to make a complex table with different cells and sections or when you need to animate cells' deleting, adding or movement. So the RxDataSources exactly for that.
Animated table editing
Look at the simple example of table animating where you can move, delete or choose cells to go to details' screen.
In the first table there are one cell type and as it will be interactive we'll use RxDataSources (if you decided to integrate RxSwift into your project, it would be better to use it permanently and everywhere).
For the simple table you have to start from SectionModel<Section, ItemType> where ItemType is your DataSource element type. For the animated table you need to use AnimatableSectionModel<Section, ItemType>. Depending on model type, its item has to conform to a specific protocol:

  • For the first case it's enough Equatable
  • For the second you need to add IdentifiableType to Equatable
We need to pay attention to IdentifiableType as if you look through GitHub questions about RxDataSource, you can find that sometimes people don't understand what's going on and why their interface works wrong.
Identity is kind of object's social security number. The constant, that will help you to identify object's identity, for example UUID.

Equatable helps to understand when the object changes its characteristic. Any change will trigger cell updating.

For example, a human: he can change the wear, hair and get a spray tan but his identity still the same and for identification you'll use relevant document.
Declare typealias AnimatableSectionModel and DataSource:
Initialize dataSource with required parameters:

  • AnimationConfiguration - set animation types for different activities
  • ConfigureCell - return the cell and bind it to viewModel. Here you can bind some activities to cell elements, for example, buttons' activity.
  • CanEditRowAtIndexPath - shows can you edit the cell or no
  • CanMoveRowAtIndexPath - shows can you move the cell or no. Always set after CanEditRowAtIndexPath.
Then bind DataSource to SectionModel and use Driver:
Use rx.itemDeleted extension to delete where indexPath returns while deleting.
To move the cell use rx.itemMoved where while moving the cell we get indexPath that had a cell and value's indexPath:
And rx.modelSelected where the object returns in selected cell:
Look at the result:
Complex tables
Tables' creating with different cells and lots of sections not that different from information above. The main difference is that instead of SectionModel you need to create two sum types:

  • for sections this sum type has to conform to SectionModelType protocol. Associated value is an array of sum type for cells
  • for the cells associated value is that you want to put into cell
In our example we use receipt details window where we have three types of cells in one section:
Create in viewModel Observable with type of sections sum and initialize it each time when you get any change in DataSource:
In ConfigureCell return required cell with switch:
Look at the result:
Thanks for reading!