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?
In iOS 14, Apple introduced new features for UICollectionView
. Lists let you include UITableView
-like sections in a UICollectionView
. Modern Cell Configuration makes registering and configuring collection view cells easier. And, Section Snapshots allow for multiple sections in a UICollectionView
, where each section can have a different layout.
In this tutorial, you’ll learn how to:
- Create an expandable list using
UICollectionLayoutListConfiguration
. - Use Modern Cell Configuration to configure
UICollectionView
cells. - Use Section Snapshots to add multiple sections to a
UICollectionView
.
UICollectionViewDiffableDataSource
and UICollectionViewCompositionalLayout
, introduced by Apple in iOS 13. If you haven’t used these before, check out Collection View and Diffable Data Source and Modern Collection Views with Compositional Layouts.
Without further ado, it’s time to get started!
Getting Started
Download the project materials using the Download Materials button at the top or bottom of this tutorial. Open the starter project in Xcode. Build and run.
You’ll see an empty Pet Explorer screen. It’s part of Get a Pet, an app that displays pets available for adoption. You’ll build on top of this app. In the final version, you can browse through pet categories and select a pet to view its details. Then when you’ve found a pet you like, you can tap Adopt to adopt the pet.
The completed app’s Pet Explorer screen shows the available and adopted pets:
Notice the cute dog Diego. When you complete this tutorial, you’ll be the proud owner of this virtual puppy. :]
Open Xcode. Browse around the project. When the app starts, it sets a navigation controller as the initial view controller using a PetExplorerViewController
as the root view controller. Open Main.storyboard to check out this setup.
Open PetExplorerViewController.swift to explore this file. PetExplorerViewController
‘s collectionView
is empty. Later, you’ll populate it with list items that represent pets and pet categories.
Pet.swift has all the data related to pets.
The DataSource
typealias is for convenience. You’ll use it later when configuring the UICollectionView
data source.
The enum Section
represents sections of the UICollectionView
for .availablePets
and .adoptedPets
.
Finally, in the PetExplorerViewController
extension, you’ll find pushDetailForPet(_:withAdoptionStatus:)
. This method presents PetDetailViewController
when the user selects an item.
Open PetDetailViewController.swift. It’s a simple view controller class that displays the pet’s image, name and birth year.
Now that you’ve explored the app’s structure, it’s time to learn about UICollectionView
lists next.
What is a List?
A list is a table view lookalike in a UICollectionView
. You can create a list by applying a configurable UICollectionViewCompositionalLayout
to a section of a UICollectionView
while using only a small amount of code.
You can configure a list to display hierarchical data, with the possibility to collapse and expand list items or to look similar to a traditional table view. If you need a table view in your app you can either use a list with the UICollectionView
API or use the traditional UITableView
.
In most cases, a list is easier to create and configure.
Now it’s time to create your first list.
Creating a List
You’ll create a flat list that shows the pet categories. This will be your first table view without using UITableView
. For a flat list, the advantages of UICollectionView
list over UITableView
may not be immediately apparent. Later, when you’ll make the list expandable, you’ll discover the real benefits of using UICollectionView
list.
UICollectionView
architecture has a clean separation between layout, presentation and data. The sample code for this tutorial follows this pattern. Every time you add a new feature to Get a Pet, you’ll add a block of code for layout first, then for presentation and finally for data.
Configuring the Layout
With iOS 13, Apple introduced UICollectionViewCompositionalLayout
, a new API for building complex layouts. In iOS 14, Apple has added:
static func list(using configuration: UICollectionLayoutListConfiguration) ->
UICollectionViewCompositionalLayout
This enables you to create a list layout in one line of code, without the need for detailed knowledge of the UICollectionViewCompositionalLayout
API. You can configure the appearance, colors, separators, headers and footers of the list with UICollectionLayoutListConfiguration
.
It’s time to apply this to your code:
Open PetExplorerViewController.swift. Add the following method below the line with // MARK: - Functions
:
func configureLayout() {
// 1
let configuration = UICollectionLayoutListConfiguration(appearance: .grouped)
// 2
collectionView.collectionViewLayout =
UICollectionViewCompositionalLayout.list(using: configuration)
}
This configures the layout of the collectionView
. Here, you:
- Create a
configuration
with.grouped
appearance. This gives you a layout configuration that looks like a table view. - Next, you create a
UICollectionViewCompositionalLayout
with list sections, that uses theconfiguration
. You’ll apply this layout to thecollectionView
.
As you can see, the entire layout configuration is only two lines of code.
Call this method at the end of viewDidLoad()
by adding:
configureLayout()
Configuring the Presentation
Now it’s time to create a collection view cell for the list. The cell displays the pet category. You’ll learn about the new way to register cells.
Inside the first PetExplorerViewController
extension block, add:
// 1
func categoryCellregistration() ->
UICollectionView.CellRegistration<UICollectionViewListCell, Item> {
// 2
return .init { cell, _, item in
// 3
var configuration = cell.defaultContentConfiguration()
configuration.text = item.title
cell.contentConfiguration = configuration
}
}
This is your first encounter with modern cell registration and configuration. Here’s what the code does:
-
categoryCellregistration()
creates a cell registration for a cell of typeUICollectionViewListCell
and a data item of typeItem
. This is the modern way of registering collection view cells. - You create the cell registration, passing in a closure to configure the cell. The closure is called when a cell needs to render.
- Then you configure the cell. The pet category is available in
item.title
. Don’t worry if you don’t understand what’s going on yet. This tutorial has an entire section about modern cell configuration.
You’ll call categoryCellregistration()
when configuring the data source.
Configuring the Data
You configured the layout and the cells for the collection view. Now you need a mechanism to create these cells based on the underlying data for the collection view. That’s where the data source comes in.
Add the following method to PetExplorerViewController
:
func makeDataSource() -> DataSource {
// 1
return DataSource(collectionView: collectionView) {
collectionView, indexPath, item -> UICollectionViewCell? in
// 2
return collectionView.dequeueConfiguredReusableCell(
using: self.categoryCellregistration(), for: indexPath, item: item)
}
}
Here’s what you did:
- You create and return a
DataSource
, passing incollectionView
and a closure that provides aUICollectionViewCell
to the data source. - Inside the closure, you ask
collectionView
to dequeue aUICollectionViewCell
. Then you pass the cell registration as a parameter, socollectionView
will know which cell type it has to dequeue.categoryCellregistration()
, which you created a moment ago, contains the logic for the cell configuration.
Add the following property to PetExplorerViewController
:
lazy var dataSource = makeDataSource()
This creates the data source for collectionView
when it’s first needed because you used lazy
in the declaration.
You configured collectionView
‘s layout, presentation and data. Now you’ll populate collectionView
with data items.
Still in PetExplorerViewController.swift, add the following method to PetExplorerViewController
:
func applyInitialSnapshots() {
// 1
var categorySnapshot = NSDiffableDataSourceSnapshot<Section, Item>()
// 2
let categories = Pet.Category.allCases.map { category in
return Item(title: String(describing: category))
}
// 3
categorySnapshot.appendSections([.availablePets])
// 4
categorySnapshot.appendItems(categories, toSection: .availablePets)
// 5
dataSource.apply(categorySnapshot, animatingDifferences: false)
}
This code uses diffable data source to update the list’s content. Apple introduced diffable data source in iOS 13. The code doesn’t have any new iOS 14 features yet. That’ll change when you make the list expandable and add section snapshots to the list.
With applyInitialSnapshots()
you:
- Create a
categorySnapshot
that holds the pet category names. - Then create an
Item
for eachcategory
and add it tocategories
. - Append
.availablePets
tocategorySnapshot
. - Then append the items in
categories
to.availablePets
ofcategorySnapshot
. - Apply
categorySnapshot
todataSource
.
You’ve added a section and indicated all the elements that belong to that section.
Now, add a call to applyInitialSnapshots()
at the end of viewDidLoad()
:
applyInitialSnapshots()
Build and run.
Congratulations! Here’s your first UICollectionView
with a list.
A list supports appearances that match the styles of a UITableView
: .plain
, .grouped
and .insetGrouped
. The list you created has the .grouped
appearance.
iOS 14 has new appearances for presenting list as sidebars: .sidebar
and .sidebarPlain
. They’re typically used as the primary view in a split view.
Now you’ll make the list expandable.