Swift
iOS development
collection view
UIKit
mobile app development

How to make a simple collection view with Swift

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

A UICollectionView is the standard UIKit view for showing a grid or list of repeated items. Even a simple collection view needs three pieces: a layout, a data source, and a cell class. Once those are in place, the structure is straightforward.

The Smallest Useful Setup

For a beginner-friendly UIKit example, create a view controller that owns a collection view and provides some sample data.

swift
1import UIKit
2
3final class SimpleCell: UICollectionViewCell {
4    static let reuseID = "SimpleCell"
5
6    private let label = UILabel()
7
8    override init(frame: CGRect) {
9        super.init(frame: frame)
10
11        contentView.backgroundColor = .systemBlue
12        contentView.layer.cornerRadius = 10
13
14        label.translatesAutoresizingMaskIntoConstraints = false
15        label.textAlignment = .center
16        label.textColor = .white
17        contentView.addSubview(label)
18
19        NSLayoutConstraint.activate([
20            label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
21            label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
22            label.topAnchor.constraint(equalTo: contentView.topAnchor),
23            label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
24        ])
25    }
26
27    required init?(coder: NSCoder) {
28        fatalError("init(coder:) has not been implemented")
29    }
30
31    func configure(text: String) {
32        label.text = text
33    }
34}

The cell only needs a label and a reuse identifier.

Build the View Controller

Now create the collection view itself.

swift
1import UIKit
2
3final class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
4    private let items = ["One", "Two", "Three", "Four", "Five", "Six"]
5    private var collectionView: UICollectionView!
6
7    override func viewDidLoad() {
8        super.viewDidLoad()
9        view.backgroundColor = .systemBackground
10
11        let layout = UICollectionViewFlowLayout()
12        layout.minimumLineSpacing = 12
13        layout.minimumInteritemSpacing = 12
14        layout.sectionInset = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
15
16        collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
17        collectionView.translatesAutoresizingMaskIntoConstraints = false
18        collectionView.backgroundColor = .systemBackground
19        collectionView.dataSource = self
20        collectionView.delegate = self
21        collectionView.register(SimpleCell.self, forCellWithReuseIdentifier: SimpleCell.reuseID)
22
23        view.addSubview(collectionView)
24
25        NSLayoutConstraint.activate([
26            collectionView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
27            collectionView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
28            collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
29            collectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
30        ])
31    }
32
33    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
34        items.count
35    }
36
37    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
38        guard let cell = collectionView.dequeueReusableCell(
39            withReuseIdentifier: SimpleCell.reuseID,
40            for: indexPath
41        ) as? SimpleCell else {
42            fatalError("Could not dequeue SimpleCell")
43        }
44
45        cell.configure(text: items[indexPath.item])
46        return cell
47    }
48
49    func collectionView(_ collectionView: UICollectionView,
50                        layout collectionViewLayout: UICollectionViewLayout,
51                        sizeForItemAt indexPath: IndexPath) -> CGSize {
52        let width = (collectionView.bounds.width - 52) / 2
53        return CGSize(width: width, height: 80)
54    }
55}

This produces a simple two-column grid.

What Each Part Does

The collection view needs a layout object to decide item positioning. Here that is UICollectionViewFlowLayout.

The data source answers two core questions:

  • how many items exist
  • what cell should appear for each item

The delegate layout method decides item size. Without that, the flow layout falls back to its default sizing behavior.

Registering and Reusing Cells

Collection views do not create a new view for every item permanently. They reuse cells as items scroll on and off screen.

That is why registration and dequeuing matter. You register the cell class once, then dequeue reusable cells inside cellForItemAt.

If the reuse identifier does not match, the app crashes. That is one of the most common beginner errors.

Storyboard Versus Code

You can build the same setup in Interface Builder, but doing it in code makes the moving parts more explicit:

  • the layout is created directly
  • the cell is registered directly
  • the constraints are visible in one place

For learning the API, that clarity is useful.

Common Pitfalls

A common mistake is forgetting to set the data source. If dataSource is nil, no items appear even though the collection view itself is visible.

Another mistake is forgetting to register the cell class or nib before dequeuing it.

A third issue is miscalculating item width so the cells overflow or leave unexpected gaps. Test on different screen sizes and use the collection view width, not a hardcoded device width.

Summary

  • A simple collection view needs a layout, a data source, and a reusable cell
  • 'UICollectionViewFlowLayout is the easiest starting point'
  • Register the cell class before dequeuing it
  • Implement numberOfItemsInSection and cellForItemAt to show data
  • Use delegate sizing or layout configuration to control the grid appearance

Course illustration
Course illustration

All Rights Reserved.