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.
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.
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:
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