iOS development
Swift programming
UICollectionView
iOS UI components
mobile app development

Creating a UICollectionView programmatically

Master System Design with Codemia

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

Introduction

Creating a UICollectionView programmatically gives you full control over layout, registration, and constraints without relying on Storyboards. The pattern is straightforward once you break it into parts: create a layout, create the collection view, register a cell, and implement the data source and delegate methods. Programmatic setup is especially useful in reusable components, modular UI code, and dynamic layouts.

Start with a Layout

Every collection view needs a layout object. A UICollectionViewFlowLayout is the simplest starting point.

swift
1import UIKit
2
3let layout = UICollectionViewFlowLayout()
4layout.scrollDirection = .vertical
5layout.minimumLineSpacing = 12
6layout.minimumInteritemSpacing = 12
7layout.sectionInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)

This layout decides spacing, direction, and basic item placement.

Create the Collection View

In a view controller, instantiate the collection view with the layout and constrain it to the parent view.

swift
1import UIKit
2
3final class ColorsViewController: UIViewController {
4    private let items = ["Red", "Blue", "Green", "Orange"]
5    private var collectionView: UICollectionView!
6
7    override func viewDidLoad() {
8        super.viewDidLoad()
9        view.backgroundColor = .systemBackground
10
11        let layout = UICollectionViewFlowLayout()
12        layout.scrollDirection = .vertical
13        layout.minimumLineSpacing = 12
14        layout.minimumInteritemSpacing = 12
15        layout.sectionInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
16
17        collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
18        collectionView.translatesAutoresizingMaskIntoConstraints = false
19        collectionView.backgroundColor = .systemBackground
20        collectionView.dataSource = self
21        collectionView.delegate = self
22        collectionView.register(ColorCell.self, forCellWithReuseIdentifier: ColorCell.reuseID)
23
24        view.addSubview(collectionView)
25        NSLayoutConstraint.activate([
26            collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
27            collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
28            collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
29            collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
30        ])
31    }
32}

That is the core setup. The collection view exists, is attached to the view hierarchy, and knows which cell class to reuse.

Build a Custom Cell

A custom cell keeps presentation logic out of the controller.

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

Programmatic cells are a good place to add subviews, Auto Layout constraints, and styling.

Implement the Data Source

Now provide the item count and cell configuration.

swift
1extension ColorsViewController: UICollectionViewDataSource {
2    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
3        items.count
4    }
5
6    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
7        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ColorCell.reuseID, for: indexPath) as! ColorCell
8        cell.configure(with: items[indexPath.item])
9        return cell
10    }
11}

Without these methods, the collection view appears but shows no content.

Size the Items

If you use UICollectionViewFlowLayout, implement UICollectionViewDelegateFlowLayout for item sizing.

swift
1extension ColorsViewController: UICollectionViewDelegateFlowLayout {
2    func collectionView(
3        _ collectionView: UICollectionView,
4        layout collectionViewLayout: UICollectionViewLayout,
5        sizeForItemAt indexPath: IndexPath
6    ) -> CGSize {
7        let width = (collectionView.bounds.width - 44) / 2
8        return CGSize(width: width, height: 120)
9    }
10}

This creates a simple two-column grid with spacing already accounted for.

When Programmatic Setup Helps Most

Code-based setup is especially useful when:

  • the UI is reused across modules
  • layout changes depend on runtime configuration
  • the project avoids Storyboards by convention
  • the collection view lives inside a custom reusable view

It also makes review diffs cleaner because the behavior is visible in Swift code instead of Interface Builder metadata.

Common Pitfalls

  • Forgetting to register the cell class or nib before dequeueing cells.
  • Adding the collection view without disabling autoresizing masks or adding constraints.
  • Implementing the collection view but forgetting to set the dataSource and delegate.
  • Hardcoding item sizes without accounting for section insets and spacing.
  • Putting too much presentation logic into the view controller instead of a custom cell.

Summary

  • A programmatic UICollectionView starts with a layout, a registered cell, and data source wiring.
  • 'UICollectionViewFlowLayout is the easiest default layout for grids and lists.'
  • Custom cells keep styling and subview configuration organized.
  • Auto Layout constraints are required if the collection view is created in code.
  • Programmatic setup is ideal when you want precise control and reusable UI code.

Course illustration
Course illustration

All Rights Reserved.