iOS 14 Tutorial: UICollectionView List
In this tutorial, you’ll learn how to create lists, use modern cell configuration and configure multiple section snapshots on a single collection view. By Peter Fennema.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
iOS 14 Tutorial: UICollectionView List
25 mins
- Getting Started
- What is a List?
- Creating a List
- Configuring the Layout
- Configuring the Presentation
- Configuring the Data
- Making the List Expandable
- Configuring the Presentation
- Configuring the Data
- What is Modern Cell Configuration?
- Configuring the Cells
- Adopting a Pet
- What is a Section Snapshot?
- Adding a Section for Adopted Pets
- Configuring the Presentation
- Configuring the Data
- Where to Go From Here?
Making the List Expandable
It’s time to add pets to the categories.
Here, you’ll discover the powerful benefits of UICollectionView
lists. With a UITableView
, you would have to handle taps on category cells and pet cells, maintain the visible and expanded state of cells and write the code that shows or hides the pet cells.
With a UICollectionView
list, you only have to provide a hierarchical data structure of categories and pets. The list will take care of the rest. You’ll soon discover how much you can achieve with only a few lines of code.
Pet.swift has the data for all pets and the categories they belong to. There’s no need to change anything in the layout, so you’ll start with the presentation.
Configuring the Presentation
Earlier, you created a cell for a pet category. You learned about the new way to register cells. Here you’ll do the same, this time to create a cell for a pet. The cell will display the pet’s name.
In PetExplorerViewController.swift, add:
func petCellRegistration() ->
UICollectionView.CellRegistration<UICollectionViewListCell, Item> {
return .init { cell, _, item in
guard let pet = item.pet else {
return
}
var configuration = cell.defaultContentConfiguration()
configuration.text = pet.name
cell.contentConfiguration = configuration
}
}
petCellRegistration()
is similar to categoryCellregistration()
you added earlier. You create a cell registration and use modern cell configuration to configure the cell. Here you use defaultContentConfiguration()
and then assign the pet name as the text to display.
You’ll call petCellRegistration()
when configuring the data source.
Next, you’ll make the list expandable by adding an outline disclosure accessory to the category cell. This indicates that an item can expand and collapse. When you tap a category, the list expands and shows the pets for that category.
In categoryCellregistration()
and right below cell.contentConfiguration = configuration
, add:
// 1
let options = UICellAccessory.OutlineDisclosureOptions(style: .header)
// 2
let disclosureAccessory = UICellAccessory.outlineDisclosure(options: options)
// 3
cell.accessories = [disclosureAccessory]
Here, you:
- Create
options
you want to apply todisclosureAccessory
. You use.header
style to make the cell expandable. - Then, create a
disclosureAccessory
with the configuredoptions
. - Apply the accessory to the cell. Cells can have more than one accessory, so you add
disclosureAccessory
in an array.
Build and run.
The outline disclosure is visible, but when you tap a cell, nothing happens. Why? You didn’t add pets to their categories yet. You’ll do that next.
Configuring the Data
Next, you’ll learn how to add hierarchical data to a list. When you’re done, you’ll see that the list automatically supports collapsing and expanding cells.
Now, adapt the data source to add the pet cells to their categories.
In makeDatasource()
, replace:
return collectionView.dequeueConfiguredReusableCell(
using: self.categoryCellregistration(), for: indexPath, item: item)
With:
if item.pet != nil {
// 1
return collectionView.dequeueConfiguredReusableCell(
using: self.petCellRegistration(), for: indexPath, item: item)
} else {
// 2
return collectionView.dequeueConfiguredReusableCell(
using: self.categoryCellregistration(), for: indexPath, item: item)
}
An item can either represent a category or a pet. This depends on the value of pet
. In this code, the collectionView
will dequeue:
- A cell for a pet if
item.pet
is notnil
. - A cell for a category if
item.pet
isnil
.
You configured everything needed to display pets but didn’t add any pets yet. For this to work, you have to update the initial snapshot of the data.
Replace the body of applyInitialSnapshots()
with:
// 1
var categorySnapshot = NSDiffableDataSourceSectionSnapshot<Item>()
// 2
for category in Pet.Category.allCases {
// 3
let categoryItem = Item(title: String(describing: category))
// 4
categorySnapshot.append([categoryItem])
// 5
let petItems = category.pets.map { Item(pet: $0, title: $0.name) }
// 6
categorySnapshot.append(petItems, to: categoryItem)
}
// 7
dataSource.apply(
categorySnapshot,
to: .availablePets,
animatingDifferences: false)
To build the hierarchical relation between categories and pets you:
- Create a
categorySnapshot
of typeNSDiffableDataSourceSectionSnapshot
. This is a section snapshot. With a section snapshot it’s possible to represent data with a hierarchical structure, such as an outline with expandable items.
For now, this is all you need to know about section snapshots. You’ll learn more about section snapshots later in this tutorial. - Then, loop over the categories in
Pet.Category.allCases
. Within the loop, you add the pets to their categories. - Create a
categoryItem
. - Append the
categoryItem
to thecategorySnapshot
. - Then, create an array,
petItems
, containing all pets that belong to the currentcategory
. - Create the hierarchical relationship between categories and pets by appending the
petItems
to the currentcategoryItem
. - Apply
categorySnapshot
to.availablePets
ofdataSource
.
Build and run.
Tap a category. The list expands and shows the pet names. Great!
Now it’s time to make the cells look a little better.
What is Modern Cell Configuration?
If you’ve used a UITableView
or UICollectionView
, you’re used to configuring your cells by directly setting their properties. In iOS 14, cell configuration can be entirely decoupled from the cell itself.
You create a cell content configuration of type UIContentConfiguration
. Then, you set the properties of this content configuration as you like. Similarly, you can create a cell background configuration of type UIBackgroundConfiguration
.
The result is a reusable configuration you can apply to any cell you like.
It’s time to see how this works!
Configuring the Cells
You just learned the theory of modern cell configuration. Now, you’ll put cell content configuration into practice by adding code to update the pet cell to show a pet’s image and age. In the next section, you’ll apply cell background configuration.
In petCellRegistration()
, replace:
var configuration = cell.defaultContentConfiguration()
configuration.text = pet.name
cell.contentConfiguration = configuration
With:
// 1
var configuration = cell.defaultContentConfiguration()
// 2
configuration.text = pet.name
configuration.secondaryText = "\(pet.age) years old"
configuration.image = UIImage(named: pet.imageName)
// 3
configuration.imageProperties.maximumSize = CGSize(width: 40, height: 40)
// 4
cell.contentConfiguration = configuration
Here, you see cell content configuration in action. You:
- Create a
configuration
of typeUIListContentConfiguration
with default styling. With this configuration, you have a cell where you can set an image, text and secondary text. - Apply the pet’s data to the configuration, including an image of the pet.
- Set the size of the image.
- Apply
configuration
tocontentConfiguration
of the cell.
Build and run.
Suddenly, the pets look more cuddly. Are you feeling motivated to adopt one? :]