UICollectionView
cellForItemAtIndexPath
iOS development
debugging
Swift

UICollectionView's cellForItemAtIndexPath is not being called

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

If collectionView(_:cellForItemAt:) is never called, the collection view is usually not ready to ask for cells yet. The problem is almost always in one of four places: data source wiring, item count, cell registration, or layout and visibility.

Check the Data Source First

The collection view will not request a cell unless it has a data source and that data source reports at least one item.

swift
1import UIKit
2
3final class UsersViewController: UIViewController, UICollectionViewDataSource {
4    @IBOutlet private weak var collectionView: UICollectionView!
5    private var users = ["Ana", "Ben", "Cara"]
6
7    override func viewDidLoad() {
8        super.viewDidLoad()
9        collectionView.dataSource = self
10        collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
11        collectionView.reloadData()
12    }
13
14    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
15        return users.count
16    }
17
18    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
19        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
20        cell.contentView.backgroundColor = .systemBlue
21        return cell
22    }
23}

If numberOfItemsInSection returns 0, cellForItemAt will never be called. That is normal behavior, not a collection-view bug.

Verify Cell Registration and Reuse Identifier

The next thing to check is whether the cell is registered or configured correctly in Interface Builder.

If you register in code:

swift
collectionView.register(MyCell.self, forCellWithReuseIdentifier: "MyCell")

then your dequeue call must use the exact same identifier:

swift
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath)

For storyboard-based cells, confirm that:

  • the collection view cell exists in the storyboard
  • the reuse identifier matches exactly
  • the outlet to the collection view is connected

Layout and Geometry Matter

Even with a valid data source, a collection view may still not ask for visible cells if its geometry is broken.

Common examples:

  • the collection view frame is zero
  • the item size is zero
  • constraints collapse the view offscreen
  • the collection view is hidden or covered

A simple diagnostic:

swift
1override func viewDidLayoutSubviews() {
2    super.viewDidLayoutSubviews()
3    print("collection frame:", collectionView.frame)
4    print("content size:", collectionView.collectionViewLayout.collectionViewContentSize)
5}

If the frame or content size is zero, the view cannot display cells correctly.

Provide a Real Item Size

If you use UICollectionViewFlowLayout, make sure the item size is not accidentally zero.

swift
1extension UsersViewController: UICollectionViewDelegateFlowLayout {
2    func collectionView(
3        _ collectionView: UICollectionView,
4        layout collectionViewLayout: UICollectionViewLayout,
5        sizeForItemAt indexPath: IndexPath
6    ) -> CGSize {
7        return CGSize(width: collectionView.bounds.width - 32, height: 60)
8    }
9}

Broken sizing logic is one of the fastest ways to end up with a collection view that technically exists but never renders cells.

Async Data Requires a Reload

If your backing data is loaded asynchronously, the collection view must be reloaded after the data arrives and on the main thread.

swift
1func loadUsers() {
2    apiClient.fetchUsers { [weak self] result in
3        guard let self else { return }
4        switch result {
5        case .success(let users):
6            DispatchQueue.main.async {
7                self.users = users
8                self.collectionView.reloadData()
9            }
10        case .failure(let error):
11            print(error)
12        }
13    }
14}

If reloadData() runs before the model is updated, or runs off the main thread, the visible result can be empty.

A Good Debugging Sequence

When diagnosing this problem, check methods in this order:

  1. viewDidLoad
  2. numberOfItemsInSection
  3. cellForItemAt

If viewDidLoad runs but numberOfItemsInSection does not, the data source is probably not connected.

If numberOfItemsInSection runs and returns a positive count but cellForItemAt still does not, the next suspects are layout, visibility, or registration.

Common Pitfalls

Forgetting to assign collectionView.dataSource is one of the most common causes.

Returning zero items because the model has not loaded yet makes the collection view behave correctly but look broken.

Using mismatched reuse identifiers or failing to register the cell causes dequeue and rendering problems.

Letting Auto Layout or item-size logic collapse the view to zero prevents cells from being requested visibly.

Summary

  • 'cellForItemAt is only called when the collection view has a data source, positive item count, and visible layout.'
  • Always verify numberOfItemsInSection before chasing more complex explanations.
  • Check reuse identifiers and cell registration carefully.
  • Inspect frame size, content size, and item size when the view appears empty.
  • Reload data on the main thread after asynchronous model updates.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.