Diffable data source an iOS 13 API for UITableView and UICollectionView

Ever thinking about writing, tableview or collection view without using cellForRowAtIndexPath, numberOfRowsInSection, reloadData etc.. Even far update the data source without error prone situations or with smooth animation. Some what exaggeration right! Last year apple introduced something which is beyond our imagination.

All New UITableView and UICollectionView

I was thinking to write about a tech topic from a past few months. Until now I never found a topic which actually impressed me. Thats how big players says but that was not my case. I was looking for something which is simple and easy to understand me first ;).

Lets discuss,

some basics

What is a data source?

Something which is capable for providing data to the view. Usually the word datasource comes to relevant when we spoke about UITableView or UICollectionView. As usual when we display a list of data to the view, the datasource will be the one who providing data.

Now, What is diffable data source ?

Prior to come to the diffable data source, Let’s speak about some generic questions that you always raised in you mind when you using tableview or collection view.

  1. How can we reduce code by avoiding cell delegate and data source methods ?
  2. Do we have any alternate mechanism for generating table view and collection view ?
  3. And upmost when we do operations in a table datasource how to display an stutter free animation?
  4. When we perform datasource operations like insertion or deletions, how to avoid the error prone situations like the internal inconsistency exceptions?

Here comes our diffable data source. The diffable datasource replaces the old UITableViewDataSource/UICollectionViewDataSource with the new UITableViewDiffableDataSource/UICollectionViewDiffableDataSource.

The diffable (differently abled) part of UICollectionViewDiffableDataSource means that whenever you update the items you’re displaying, the collection view will automatically calculate the difference between the updated collection and the one previously shown. This will in turn cause the collection view to animate the changes, such as updates, insertions and deletions.

Lets dig deep

Prior to iOS 13, everybody needs to configure UITableViews data source by adopting UITableViewDataSource. Likewise in collection view. This protocol tells the view what cell to display, how many cells to display, which section to display like so.

Interestingly using our new diffable data source, we tell what sections and items to display instead of telling the data source to how many items to display.

Diffable Data Source manages the data sources both in TableView and CollectionView by using the snapshot.

Snapshot acts as a source of truth between our view and data source.
Whenever there are changes in our model, we just need to construct a new snapshot and applies it to the current snapshot. All the diffing, view update with animation will be performed automagically for us. Also, we don’t need to deal with indexPath when we dequeue our cell, the exact model will be given to us to render in the cell based on generic API.

Key benefits are,

  1. Reduced code
  2. Hassle free data synchronisation
  3. Automatic data change animations

Lets build the project

To build a project using Diffable data source the key things you have to notice are

  1. Prepare Diffable data source
  2. Apply the same to the tableview using SnapShot.
  3. Thats all.

If you’ve used table views before, you should be familiar with the concept of sections and items. Exactly like the same, UITableViewDiffableDataSource has two generic types: Section type and item type.

The SectionType and ItemType are generic that we must provide when we declare and initialise the class. Both of them need to implement to Hashable protocol this is a mandatory requirement that developer must follow to make sure the diffing works correctly. Download project from following repo

The essential components from the projects are

  1. PlaceViewController — Our main ViewController class, a subclass of UITableViewController.
  2. PlaceTableViewCell — A TableViewCell that we will use to display the place

Create Model for the Section

We create an enum for Section, we will name it Location

enum Location: String {
case London
case Paris
}

The enum raw type will be String. This enum will automatically conforms to Hashable protocol using the rawValue as the unique hashValue.

Create Model for the Row

For the row representation, we will create struct called Place. The struct has properties such as name, description, imageName. We also have the id as the properties to make sure each of the place instance is unique.

struct Place: Decodable {

let id: String
let name: String
let description: String
let imageName: String
}

Next important thing, we need to make it conform the Hashable protocol. We created an extension for the Place that implements Hashable. And we need to provide the hasher value that will be used to create the hashValue. In this case we use the id of the `Place` into the hasher.

extension Place: Hashable {

func hash(into hasher: inout Hasher) {

hasher.combine(id)
}
}

To display data in the TableView we will be loading data from JSON and decode it into Place instances.
Next, we will associate the places for each of the Location enum.

Additionally we Subclassing UITableViewDiffableDataSource to display section title

We are subclassing the UITableViewDiffableDataSource due to override one of the method to provide city name as the title for our section. If your app don’t have any section header, you don’t need to subclass it.

class PlaceTableViewDiffableDataSource: UITableViewDiffableDataSource<Location, Place> {

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {

return snapshot().sectionIdentifiers[section].rawValue.uppercased()
}
}

In our case we have to override only one method, tableView(_:titleForHeaderInSection:). And we access the snapshot property section identifiers array and passing the section index to retrieve the associated Location.

Finally wire up the TableViewDiffableDataSource in TableView

  1. Initialise diffable data source
  2. Setup and Applying Snapshot

Initialising PlaceTableViewDiffableDataSource. The initialiser accepts the TableView and a closure. The closure parameter are the TableView, IndexPath, and the associated Place, this closure will be invoked when the TableView needs to dequeue the cell. We don’t need to retrieve the place manually using the IndexPath anymore as it is already passed in the parameter. In this case we just need to dequeue the cell from the TableView using the reuse identifier and update the cell with the place.

private func setupTableView() {

diffableDataSource = PlaceTableViewDiffableDataSource(tableView: tableView) { (tableView, indexPath, place) -> UITableViewCell? in

let cell = tableView.dequeueReusableCell(withIdentifier: “Cell”, for: indexPath) as! PlaceTableViewCell

cell.data = place
return cell
}
}

For building and applying snapshot to diffable data source, we will create a method called buildAndApplySnapshot. The steps we will perform are

  1. Initialise a new snapshot using the NSDiffableDataSourceSnapshot class using the Location and Place to represent the section and item.
  2. Looping the json array, for each element we are appending the location to the snapshot. Also the associated places to the location.
  3. Finally, we invoke the diffableDataSource apply method passing the new snapshot.

Then, we will add the invocation of the methods in the viewDidLoad method.

override func viewDidLoad() {
super.viewDidLoad()

setupTableView()
buildAndApplySnapshot()
}

Thats all.

Now we just replaced our conventional implementation with new diffable data source. So whats our actual benefit code reduction. Is that all, of-course not. Let’s see the actual magic.

Perform some operations, let’s do an update or delete and you can see how beautifully it animates and reset view. Download the code and check it.

The next part of this series more focused on coding by demonstrating advanced usage of diffable data source.

Thank you all for reading.

Got to Part 2

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store