This post is part of a series written by our developers that documents their journey in a cross-platform mobile app development project. They set out to improve an internal process, create educational content for the developer community, and explore new craft beers and a vintage arcade.

 

This is the first in a four-part iOS UICollectionView tutorial series about doing custom layout for collection views in iOS using Swift.

A central piece of functionality in the Intertech Time Entry App is the display of hours spent working on different projects. Early conversations about how to display these entries highlighted a common pitfall for developers. We sometimes lean towards implementations and paradigms that are familiar to us. In this case we have a list of entries. How do we display lists in iOS? UITableView of course! Fortunately we had the advantage of working with talented UX designers. They provided us with a design that looked great and was much more helpful to the user. In this series of articles we will walk through the challenge of transforming a simple and boring list into an awesome, custom design.

Simple List to Collection View

Figure 1

Table Layout

Let’s take a look at how this might have ended up if we had allowed ourselves to be trapped by developer groupthink. It only takes 15 lines of Swift code to create a basic table view controller.

import UIKit

class TimeEntryTableViewController : UITableViewController {
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1;
    }
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return sampleData.count;
    }
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
        let data = sampleData[indexPath.item]
        cell.textLabel?.text = data.0
        cell.detailTextLabel?.text = "\(data.1) (\(data.2))"
        return cell;
    }
}

let sampleData = [
    ("8/3/15", "Microsoft", 8),
    ("8/4/15", "Google", 2),
    // Elements removed...
    ("8/27/15", "Microsoft", 6),
    ("8/28/15", "Google", 8),
]

If you combine that with a UITableView on the Storyboard you can quickly get our list of time entries on the screen. The table view is seen on the left in Figure 1. It does technically present all of the information but it isn’t very useful, and it isn’t very pretty. With a basic list it’s difficult to get a quick summary of where you spent your time. You may argue that we could add some sections to break up the list but even then the experience isn’t as good as it could be.

Introducing UICollectionView

We’ll take the first step towards our complete transformation by introducing UICollectionView. The UICollectionView control allows you to customize the layout of the control. This gives you a tremendous amount of flexibility while still conforming to patterns that are similar to those in a table view.

Before we begin writing code we should review the three components that are required for using this type of view.

  1. UICollectionView
  2. Data Source (View Builder)
  3. Layout Object

UICollectionView itself provides the scrollable region on the screen in which to display your data. The layout object is responsible for determining the bounds (position and size) of each subview within the UICollectionView.

That just leaves the data source. I think the term data source in this case is a little misleading. The data source doesn’t just supply basic data structures to the UICollectionView. In fact, it supplies views that have been populated with data to be displayed inside UICollectionView. The data source gets a reusable view from the UICollectionView, applies the raw data to that view, and then returns it for use. If you think of the data source as a “Child View Builder” I think its purpose is clearer.

Note: The data source does not create the child views. The views are provided by the UICollectionView control. This allows for better performance in long lists by reusing a small number of views rather than creating a unique one for each item in the list.

GridSection

Figure 2

The views provided by the data source are divided into sections. Each section can have a header and footer in addition to the views for each item. For our time entries it makes sense to make each day its own section. The orange box represents a section within the collection. The blue box is a section header. Green boxes are the items, one for each time entry. We won’t use a footer in this series.

Series Articles

This series of articles will step through the process of transforming a basic list into something much more. The first article will walk through the process of creating a basic collection view. Nothing custom here but it lays the groundwork for the next two articles.

The first walkthrough, in Part 2, will show you how to put together a basic collection view using a flow layout. Part 3 will begin work on customizing the layout on a single screen. The final article will complete the process by adding scrolling support so we will be able to display long lists using the custom layout.