Lecture Handout
This lecture covers UICollectionViews -- a widely used UIKit component. You'll notice that UICollectionViews are very similar to UITableViews!
Last updated
This lecture covers UICollectionViews -- a widely used UIKit component. You'll notice that UICollectionViews are very similar to UITableViews!
Last updated
A collection view (UICollectionView
) is a subclass of UIScrollView
, which means that the user can scroll through it, either horizontally or vertically. Just like a table view, a collection view consists of sections where each section consists of 3 parts: a header, cells, and a footer. However, unlike a table view (in which each cell is constrained to be the full width of the table view), the size of the cells in a collection view can be set. In other words, a collection view is a more dynamic, customizable table view.
Like table views, UICollectionView
s are an extremely powerful type of view and are used in almost all of the successful apps today (i.e. Instagram, Photos, Stories, etc.). They provide an easy way to display a lot of information in a compact, grid-like manner.
Example 1: Netflix
Each category (e.g. "Ensemble TV Shows", "Women Who Rule The Screen", etc.) is a section is a UICollectionView
. Each show is a UICollectionViewCell
.
Example 2: Instagram
The entire feed is a UICollectionView
, and each image is a UICollectionViewCell
.
Similar to a table view, in addition to the usual initialization process for initializing any UIView
(calling the init function, set translatesAutoresizingMaskIntoConstraints
to false, adding the view as a subview to parent view, and setting up constraints), there are 4 additional things that you should do:
Set the collectionView
’s delegate
Set the collectionView
’s dataSource
Register your custom UICollectionViewCell
class
(Only for UICollectionViews!) Initialize the collectionView
with a
UICollectionViewLayout
(we use UICollectionViewFlowLayout
). Your collectionView
’s delegate should also conform to UICollectionViewDelegateFlowLayout
.
For explanations on what the first 3 mean, refer to Lecture 4: UITableViews.
In terms of 4, the initializer for a UICollectionView
takes in a frame: CGRect
and a layout: UICollectionViewLayout
. In most cases, we just use an instance of UICollectionViewFlowLayout
for this layout parameter. Why? Well, a UICollectionViewFlowLayout
is a “layout object that organizes items into a grid with optional header and footer views for each section” -- which is what we want in most cases!
Some nice properties of UICollectionViewFlowLayout
that we can set to customize our collectionView
are scrollDirection
(vertical or horizontal), minimumLineSpacing
(the minimum spacing to use between rows in the grid), minimumInteritemSpacing
(the minimum spacing to use between items in the same row), and a lot more.
The following is an example of initializing a UICollectionView
:
Let's go through what this code does, line by line.
1: Initialize a UICollectionFlowLayout
instance.
2: Set the layout's scrollDirection
to be vertically-scrolling.
3 & 4: Set the minimumLineSpacing
and minimumInteritemSpacing
to be some constant we defined in a padding
variable. This means that items in the same row will have spacing between them equal to the value stored in padding
and items on different rows will also have spacing between them equal to padding
. (Like the Instagram example!)
5: Initialize our collectionView
using the layout
instance we just created.
6: Set translatesAutoresizingMaskIntoConstraints
to false.
7 & 8: Set the delegate
and dataSource
to be self
, which is the view controller that holds this collectionView
.
9: Register our custom PhotoCollectionViewCell
to the collectionView
. This tells collectionView
that we will be dequeueing PhotoCollectionViewCell
s.
We look at this diagram again to understand the delegation that occurs. Even though the diagram uses UITableViewDataSource
/UITableViewDelegate
, this is basically the same as UICollectionViewDataSource
/UICollectionViewDelegate
except replace “rows” with “items”.
A UICollectionViewDataSource
(in most cases, the view controller) must conform to certain methods and is “responsible for providing the data and views required by a collection view.” The one method that you should always implement is:
We'll often refer to this method as cellForItemAt
. This function requires you to return a UICollectionViewCell
which will be inserted at a particular location in the collectionView
.
One parameter in this function that is important to take note of is indexPath
, which is of type IndexPath
. The indexPath
has two important properties that you may sometimes need:
1. item
(Note: for tableViews, we have rows instead of items), and
2. section
Thus, if you wanted to see what item or section the cell you’re returning is going to be used for, you can just call indexPath.item
or indexPath.section
.
Once again, let's go through the code line by line:
2. Dequeue the appropriate cell using the associated reuse identifier that you used when you registered your custom cell to the collectionView
. Make sure you cast the dequeued cell as your custom cell class!
3 & 4. It's best practice to have some configure(...)
function as a part of your custom cell class that takes in some data or model object to configure the views inside your cell. Let's say you're using some dataModelArray
as the data source for your collection view. You can access the dataModel object that this item represents using dataModelArray[indexPath.item]
.
5. Return the configured cell!
Another method that you should implement is:
We'll refer to this method as numberOfItemsInSections
.This function requires you to return an integer representing the number of rows that the section section
should have. Usually, the number of cells that you want to display in your collection view is dependent on the number of model objects that you have. For example, if you wanted to use a collection view to display a collection of photos, you would probably have an array of Photo objects. Thus, the number of cells you need in your table view is just the number of photos in that array, which you can get from photosArray.count
. However, it is also possible that you just want to create a static number of cells, in which case you can just return that constant!
Finally, while not required, you may also want to implement the following:
As the name implies, this allows you to control the number of sections that your collection view has. If you don't implement this function, your collection view will by default have one section.
A UICollectionViewDelegate
does not actually have to conform to any specific methods since all the methods are optional. However, one useful one that you may find yourself using a lot is:
We'll refer to this function as didSelectItemAt
. This is the function that gets called whenever one of the cells in collectionView
is selected by the user. Thus, if you want to trigger some sort of action or animation upon selection, this is the place you would do it. For example, if you wanted to change some data model property upon selecting a cell, you could once again access that specific data model object using indexPath.item
.
Lastly, a UICollectionViewDelegateFlowLayout
also does not actually have to conform to any specific methods since all the methods are optional. However, a method that you should implement is:
We'll refer to this method as sizeForItemAt
. This method requires you to return a CGSize
that represents the size of the cell at indexPath
. Thus, if we wanted each of our cells to be 50 pixels by 50 pixels, we would return CGSize(width: 50, height: 50)
, as in the example code snippet.
You can find a list of all the UICollectionViewDelegate
, UICollectionViewDataSource
, & UICollectionViewDelegateFlowLayout
methods in the Apple documentation, linked below.