Diffable data sources dramatically simplify the work involved in managing and updating collection and table views to create dynamic and responsive experiences in your apps. Discover how you can use section snapshots to efficiently build lists and outline collection views for iOS and iPadOS and provide support for implementing the sidebar in an iPad app. We'll also show you how to simplify cell reordering using UICollectionViewDiffableDataSource to help you streamline your code and build app interfaces more quickly.
This session builds on 2019's “Advances in UI Data Sources,” which you may want to check out first.
Welcome. My name is Steve Breen, and I'm an engineer on the UIKit team. And in this video, we're going to chat a bit about advances in Diffable Data Source for iOS 14.
So, before we dive into our content, I want to highlight a portion of the companion sample project for this video entitled "Emoji Explorer." This sample has a lot of interesting components baked right into its design.
Now, in this first section, there's a horizontally scrolling grid of emoji. This is a pretty common design element in many of today's apps. Okay, so, this section in the middle of Emoji Explorer is especially novel. It's an expandable-collapsible outline-styled UI which is new in iOS 14.
And finally, in this last section, there's a design that looks suspiciously like a UITableView right here in the middle of our UICollectionView. Okay, that's Emoji Explorer, and we'll be referring back to this throughout our video.
Okay. So, to review, Diffable Data Source, which was introduced in iOS 13, greatly simplifies the management of UI state through the addition of a new snapshot data type.
Snapshots encapsulate the entire UI state via the use of unique section and item identifiers.
So, when updating a UICollectionView, we first create a new snapshot, populate it with the current UI state, and apply it to the data source.
Diffable Data Source computes the differences and animates things automatically without any additional work needed from the application developer.
So we covered this API in detail in the WWDC 2019 video, "Advances in UI Data Sources," and I encourage you to check out that video to learn more.
So, for iOS 14, we've built on the foundation of Diffable Data Source with two new features: Section Snapshots and first class Reordering Support. Let's chat a bit about Section Snapshots.
For iOS 14, we're adding a new section snapshot right alongside the existing snapshot type we call "section snapshots." And as the name implies, section snapshots encapsulates the data for a single section in a UICollectionView. There are two reasons for this enhancement. First, to allow data sources to be more composable into section-sized chunks.
And second, to allow modeling of hierarchical data which is needed to support rendering outline-style UIs, a common visual design found all throughout iOS 14.
So let's go back to Emoji Explorer and see how section snapshots are used to build this out in our sample app.
First, in our horizontally scrolling section, we are using a single section snapshot to completely model the content found here.
Next, in our second section where we see this expandable-collapsible outline-style section, a second section snapshot is used to model this hierarchical data. And finally, in our list section, we again model this section's content with a third section snapshot.
So for Emoji Explorer, we compose our Diffable Data Source from three distinct section snapshots each representing a single section's content. Let's take a look at some API. So, here's a snippet of the new Section Snapshot API, and check out the SDK for the entire API.
So, please note that we'll use the term "snapshot" when we're referring to the original snapshot type introduced in iOS 13, which includes sections and item identifiers.
And we'll use the term "section snapshot" to refer to this new to iOS 14 type. So, glancing at this new section snapshot type, we see that it's generic over the item type.
Note there's an absence of any kind of section identifier type. section snapshots just inherently don't know what section they represent.
To add content to our section snapshot, we'll use the 'append' API.
Now, notice the optional parent parameter. When supplied, this allows us to create parent-child relationships in the section snapshot needed to model hierarchical data.
Now, we've added two new APIs to UICollectionViewDiffableDataSource to accommodate the new section snapshot type.
First, we have a new 'apply' method which takes a section snapshot and a section identifier.
Our second new API allows us to retrieve a section snapshot representing a particular section's contents. So next, let's flesh out a code snippet showing how to use snapshots and section snapshots together to build up our Collection View's content. First, we'll add sections in the order we desire by applying a snapshot to our Diffable Data Source.
And here we see, we have the sections in a particular order: 'recent,' 'top,' and 'suggested.' Now, after we have the desired section order, we're going to populate the items for each of these sections by applying section snapshots directly to each section. Let's take a look at how to create hierarchical data using this Section Snapshot API. First, we'll append some root items to our sections. Smiley, nature, food, et cetera using the 'append' API.
Recall the 'append' method has an optional 'parent' parameter. So when that's not supplied, that means apply these items to the root. So, to configure our parent-child relationship, we'll append some child items into a parent item. In this example, the parent item is "food." And that's it. We've created a section snapshot which models our application's hierarchical data. Okay. So, it should be clear by now, section snapshots are capable of representing hierarchical data.
Now, at times, it's very convenient to reason about just a portion of this hierarchical data.
So, in this code snippet, we're interested in getting all the children related to a particular parent item, optionally including the parent in a resultant section snapshot.
Okay. So, next up, let's chat a bit about expansion state.
So expansion state is managed as part of a section snapshot's state. And when building up a snapshot for display, you can easily determine whether or not a child content is initially visible by setting that item's parent expansion state.
You can also query a snapshot to determine if an item is expanded or collapsed. Note that if you mutate a section snapshot's expansion state, this won't apply until you actually apply that to the Diffable Data Source. Okay, so when a user interacts with an outline-styled UI which is configured with the new Cell Outline Disclosure Accessory, the framework will automatically update the section snapshot with the new expansion state and apply that section snapshot to the data source. Now, often it's useful to be notified about expansion state changes caused by these user interactions. For example, you may have a design that requires that a particular parent never collapse.
To support this, Diffable Data Source has new APIs for giving applications programmatic control over expansion state changes caused by user interactions. Okay, so here are these new APIs.
First, we notice that Diffable Data Source has a new property called "SectionSnapshotHandlers." The new SectionSnapshotHandlers type is a struct which is generic over item and contains five optional closures. To handle our previously mentioned requirement, we could provide a shouldCollapseItem handler which will return 'false' for a particular parent to avoid collapsing the outline. Now, we also provide support for lazy loading of expensive content with the API snapshotForExpandingParent.
So this is useful to minimize the amount of content loaded in the initial section snapshot when getting that content is expensive. So, you can load that content as needed depending on the current child snapshot's state. So, that wraps up Section Snapshots. One of the advances Diffable Data Source brings is the ability to model our Collection View's data with unique item identifiers. With these unique item identifiers, it is possible for the framework to automatically commit reordering changes on the application's behalf based on user interactions. But this isn't really enough. Our application needs to be notified that a user-initiated reordering interaction took place so that it can persist the new visual order to the application's backing store, which is its final source of truth. So, to support reordering, Diffable Data Source now has a new property: reorderingHandlers.
This a struct which contains three optional closures: canReorderItem, willReorder, and didReorder. So, to enable reordering via this new API, you'll first need to supply a canReorderItem closure. This will be called when a user attempts to start a reordering interaction. If it returns 'true,' the reordering interaction is allowed to begin. When the user is done with the reordering interaction, the didReorder closure is called to allow your application to commit the new ordering state to your application's source of truth. Note that you must provide both the canReorderItem and didReorder closure to enable the reordering feature. Okay. So, the didReorder closure passes your application a new type: NSDiffableDataSourceTransaction.
So, transactions supply all the information needed to reason about the update being performed against the Diffable Data Source. First, let's check out the NSDiffableDataSourceTransaction. This type supplies four basic pieces of information. First, we have the initialSnapshot. This is the state of the Diffable Data Source before the update is applied.
Next, we have the finalSnapshot. Now, this is the state of the Diffable Data Source after the update is applied. And we can use these item identifiers from this snapshot directly to determine the new ordering which we need to commit to our application's source of truth. Additionally, we can see the Swift standard lib CollectionDifference is also supplied. And if your application has a data type such as 'Array' for the source of truth, we can apply that CollectionDifference directly to that. And, lastly, we see a list of section transactions that provide per-section details about all the sections involved in this reordering update. Section transactions are quite similar. They have one section transaction supplied for each section involved in the reordering update. First off, we can inspect the sectionIdentifier this sectionTransaction has been applied to. And we also see we have the initial and final section snapshots, along with the CollectionDifference specific to this section's update. Okay. So, let's check out an example. Here, our backing store is an array of items supplying the source of truth for a single section Collection View.
Using the Swift standard lib CollectionDifference supplied with the transaction, we'll create a new backing store and update our source of truth directly.
Well, that wraps up our video today covering all the advances we've brought to Diffable Data Source for iOS 14.
Download the sample app. It's full of examples of how to use these new APIs. And use this code as a starting point to update your apps to take advantage of these new APIs. And watch the related videos mentioned throughout this talk to go deeper.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.