UICollectionView Tutorial: Headers, Selection and Reordering
Learn how to implement reusable views for UICollectionView section headers, select cells and reorder with drag and drop. By Fabrizio Brancati.
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
UICollectionView Tutorial: Headers, Selection and Reordering
30 mins
- Getting Started
- Adding Custom Section Headers
- Creating a UICollectionReusableView Class
- Setting the Section Header View Class
- Connecting the Section Header to Data
- Interacting With Cells
- Providing Selection Feedback
- Loading the Large Image
- Selecting Multiple Cells
- Keeping Track of Sharing
- Adding a Share Button
- Reordering Cells
- Implementing Drag Interactions
- Implementing Drop Interactions
- Making the Drop
- Where to Go From Here?
UICollectionView
is one of the most important classes in UIKit, used to display data to a user in a customized layout. An example of such a layout is the iOS Photos app, which shows your data ordered in the grid layout and allows you to select an image and share or reposition it in your grid view.
Like UITableView
, UICollectionView
can contain both homogeneous and heterogeneous collections of views embedded inside a UICollectionViewCell
. You use a layout to define how the cells are laid out. These can be either chosen from pre-existing layouts or you can define your own. A delegate allows you to respond to interaction, and a data source allows you to define what data is shown in the collection view.
If you need to brush up on the basics of UICollectionView
, check out UICollectionView: Getting Started.
In this tutorial, you’ll work on a photo-browsing app, FlickrSearch, similar to the iOS Photos app, in which you’ll use to learn how to:
- Implement reusable views for section headers.
- Interact with cells.
- Update layout based on selection.
- Share selected items to other apps.
- Reorder with drag-and-drop.
Getting Started
You can download the starter project by clicking the Download Materials button at the top or bottom of this tutorial.
Open the starter project. You’ll first need to set up the Flickr API key so your app can fetch photos. First, go to the Flickr website and sign-in or create an account if you don’t already have one. Then, click APPLY FOR A NON-COMMERCIAL KEY and complete the form. Click Submit and you’ll see your unique API key.
Now, open Flickr.swift in the Xcode project and paste the key from Flickr into the apiKey
string constant at the top of the file.
Build and run. In the search bar, enter a word and tap Search.
Adding Custom Section Headers
Play around with the starter app and you’ll observe:
- The app displays 20 photos related to each word search.
- It creates a new section in the same
UICollectionView
for each search you perform.
There are no section headers in the UICollectionView. So for your first task, you’ll add a new section header using the search text as the section title.
To display this section header, you’ll use UICollectionReusableView
. This class is like UICollectionViewCell
, except it’s usually used to display headers and footers. Like cells, UICollectionView
places them in a reuse queue rather than deleting them when they scroll out of the visible bounds.
You’ll add this element directly to the storyboard and create a subclass so it can dynamically update its title.
Creating a UICollectionReusableView Class
Create a new file to represent the custom class for the header.
- Select File ▸ New ▸ File. Select Cocoa Touch Class.
- Choose Subclass of UICollectionReusableView.
- Name the class FlickrPhotoHeaderView.
- Leave Also create XIB file unchecked.
- Select
Swift
as the language. - Click Next.
Select the starter app project’s Views folder and click Create to create the file.
Next, open Main.storyboard and select the collection view in FlickrPhotosViewController
. Select the Attributes inspector and, in the Accessories section, check the Section Header checkbox. Notice a Collection Reusable View appears in the storyboard underneath the Collection View.
Setting the Section Header View Class
Now, you’ll set your custom class as the section header view. To do this:
- Select the Collection Reusable View added in the collection view.
- Open the Identity inspector and set the Class in the Custom Class section to FlickrPhotoHeaderView.
- Next, in the Attributes inspector, set the Identifier to FlickrPhotoHeaderView.
- Also set the Background color to Opaque Separator Color to give it a nice offset from the rest of the collection view.
- Open the Size inspector and set the Height to 90.
Now open the Object library with the key combination Command-Shift-L and drag a Label onto the reusable view. Use the Auto Layout align button at the bottom of the storyboard window to pin it to the horizontal and vertical center of the view. In the Attributes inspector of the label, update the font to System 32.
Connecting the Section Header to Data
Open FlickrPhotoHeaderView.swift in an additional editor pane and Control-drag from the label in the header view over to the file and name the outlet titleLabel. It will add the following code:
class FlickrPhotoHeaderView: UICollectionReusableView {
@IBOutlet weak var titleLabel: UILabel!
}
Finally, you need to implement a new data source method to wire everything together. Open FlickrPhotosViewController+UICollectionViewDataSource.swift and add the following method:
override func collectionView(
_ collectionView: UICollectionView,
viewForSupplementaryElementOfKind kind: String,
at indexPath: IndexPath
) -> UICollectionReusableView {
switch kind {
// 1
case UICollectionView.elementKindSectionHeader:
// 2
let headerView = collectionView.dequeueReusableSupplementaryView(
ofKind: kind,
withReuseIdentifier: "\(FlickrPhotoHeaderView.self)",
for: indexPath)
// 3
guard let typedHeaderView = headerView as? FlickrPhotoHeaderView
else { return headerView }
// 4
let searchTerm = searches[indexPath.section].searchTerm
typedHeaderView.titleLabel.text = searchTerm
return typedHeaderView
default:
// 5
assert(false, "Invalid element type")
}
}
This method returns a view for a given kind of supplementary view. For this app, you only have headers, but you can also have other kinds of supplementary views.
Here’s the breakdown of this method:
- Handle the
UICollectionView.elementKindSectionHeader
kind whichUICollectionViewFlowLayout
supplies for you. By checking the header box in an earlier step, you told the flow layout to begin supplying headers. If you weren’t using the flow layout, you wouldn’t get this behavior for free. - Dequeue the header using the storyboard identifier.
- Check that the view is the right type and, if not, simply return it.
- Set the search term as the text on the view’s label.
- Assert in the case that the kind was not what was expected.
This is a good place to build and run. You’ll get a nice section header for each search, and the layout adapts nicely in rotation scenarios on all device types:
Bravo! It’s a small change, but the app looks so much better now, doesn’t it? :]
But there’s more work to do!