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.

4.7 (7) · 1 Review

Download materials
Save for later
Share
Update note: Fabrizio Brancati updated this tutorial for iOS 14.4, Swift 5.3 and Xcode 12.4. Mark Struzinski wrote a previous update, and Brandon Trebitowski wrote the original.

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.

Flickr starter project photos

Adding Custom Section Headers

Play around with the starter app and you’ll observe:

  1. The app displays 20 photos related to each word search.
  2. 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.

Dialog box for creating new FlickrPhotoHeaderView

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.

Check section header in Collection View dialog box

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.

Add New Alignment Constraints dialog

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:

  1. Handle the UICollectionView.elementKindSectionHeader kind which UICollectionViewFlowLayout 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.
  2. Dequeue the header using the storyboard identifier.
  3. Check that the view is the right type and, if not, simply return it.
  4. Set the search term as the text on the view’s label.
  5. 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:

Search results showing food photos

Bravo! It’s a small change, but the app looks so much better now, doesn’t it? :]

But there’s more work to do!