Handling iOS 14 Diffable Data Sources
Diffable data sources get section snapshots and first-class reordering support
Despite introducing SwiftUI (a declarative UI framework) with iOS 13, Apple still brought in a slew of new changes to the UIKit framework. Among the standout features were the enhancements to UICollectionView
.
Specifically, the Compositional Layouts and Diffable Data Sources APIs allowed building advanced CollectionView
layouts and centralized data sources a whole lot more easily.
iOS 14 takes it further by bringing a new cell registration API and providing out-of-the-box support for UITableView
within UICollectionView
.
But more importantly, diffable data sources in iOS 14 now include section snapshots. This means you can now update data on a per-section basis, which is immensely useful in building Outlined Styled lists, the new hierarchical design introduced with iOS 14.
First-class reordering capabilities is the other addition to diffable data sources this year.
Our Goal
- A quick recap of diffable data sources.
- Understanding how to implement section snapshots.
- Digging into the new reordering API.
Recap of Diffable Data Sources
Prior to this new declarative API, developers had to fall back on the numberOfItemsInSection
, numberOfSections
, cellForItemAt
methods for creating the data source. And to update the data, performBatchUpdates()
and reloadData()
were the go-to methods.
This approach works fine but led to a decentralized data source. Worse yet, the reloadData()
method ruined our chances of showing nice animations, while performBatchUpdates
would inadvertently lead to common mistakes such as NSInternalInconsistencyException
.
With the new diffable data sources, we have a centralized and dedicated data source wherein the data is provided through snapshots.
Snapshots represent a single state of data that doesn’t depend upon index paths for updating items. Instead, it relies on type-safe unique identifiers to identify unique sections and items.
Even better, you could set in the NSDiffableDataSourceSnapshot
instance to the UITableView
or UICollectionView
’s data source using the apply
method and let it take care of animations. Interestingly, the apply
method can be executed from the background thread as well.
All in all, diffable data sources compute differences and allow for much easier management of data sources in our UICollectionView
and UITableView
layouts. You can access dataSource.snapshot()
to access the current state of UI elements and add/remove items accordingly.
iOS 14 Introduces SectionSnapshots
Prior to iOS 14, to populate items and sections in iOS 13, we had to use the following methods on the NSDiffableDataSourceSnapshot
:
var snapshot = NSDiffableDataSourceSnapshot<String, String>() snapshot.appendSections(["1", "2"])
And to add items in a section, we’d use the following method:
snapshot.appendItems(["1.1"], toSection: "1")
snapshot.appendItems(["2.1"], toSection: "2")
So, what does the new NSDiffableDataSourceSectionSnapshot
API bring to the table considering we could already add items on a per-section basis?
Short answer: customising outlined/expandable lists.
By using the NSDiffableDataSourceSectionSnapshot
API, you can easily create and update expandable collection views with the ability to expand and collapse certain sections. This is handy in building hierarchical data.
Here are the methods exposed with the new section snapshots in iOS 14:

Now, let’s create an iOS 14 CollectionView
by using the brand new section snapshots for our data sources.
Create your data model
Our data source will hold hierarchical data of strings. So, let’s create two structs of items with a childItems
array:
Since both the parent item (the header) and childItems
are strings, we need a way to differentiate their types for the distinct UICollectionViewCell
they’d go in. Understandably, we’ll create an enum of cases for both of them:
enum OutlineItem: Hashable {
case parent(Parent)
case child(Child)
}
Now that our data model is ready, here’s a sneak peek at our dummy data that’ll be used to populate UICollectionView
:

Create our diffable data source
By using the new iOS 14 cell registration techniques, we don’t need to use the traditional cell identifier way of initializing UICollectionViewCell
.
Here’s a look at how to create and display contents in the iOS 14 UICollectionView.CellRegistration
and pass them to the UICollectionViewDiffableDataSource
:
Note that we’ve registered two cells. One acts as the root of each section and contains the disclosure indicator. The other is used to display the contents of each child item.
Now that our data source is ready, it’s time to set it on the CollectionView
:
private lazy var dataSource = makeDataSource()
Finally, we’ll apply the snapshot on the data source above.
Construct section snapshots
A section snapshot is constructed in the following way:
We’ve iterated over the hierarchical
data and set the parent instance as the header of each section, with the childItems
set within it. Also, we’ve expanded each header section to display all items (you can configure this to hide/expand only specific sections as well).
Finally, the section snapshot is applied to the root section of the UICollectionView
and the app looks like the following when run on the simulator:

The full source code of the UICollectionView
+ diffable data sources and section snapshots is available on GitHub.
You can also customise the expansion states of the various section items by setting the sectionSnapshotHandlers
on the dataSource
. SectionSnapshotHandler<Item>
provides different closures, such as shouldCollapseItem
, willCollapseItem
, willExpandItem
, and shouldExpandItem
.
Using the New Reordering API
While section snapshots help to generate expandable lists and determine nested levels of items (the root of the list), there’s also a reordering API that can be quickly plugged onto our diffable data sources.
Specifically, to enable reordering, you need to define the following two closures:

Understandably, for cell registration, you need to set an accessory in the following way:
cell.accessories = [.reorder(displayed:.always)]
Note: For brevity’s sake, we set the reordering icon to always be displayed. But it's recommended to set an Edit
button that toggles between whenEditing
and whenNotEditing
states for enabling/disabling reordering.

The didReorder
and willReorder
closures pass a new type known as NSDiffableDataSourceTranscation
.
The transaction consists of all the relevant information needed to update the diffable data source:

CollectionDifference
is a new type introduced with Swift 5.1. It describes the insertion and removal of items across two collection states.
So, you can simply update the original data source with the reordered transaction inside the didReorder
closure in the following way:
originalDataSource.applying(transaction.difference)
Conclusion
That concludes this article about the changes to iOS 14 diffable data sources. By using section snapshots and the new reordering API, you can easily compose and update chunks of data in your CollectionViews
.
Thanks for reading.