UICollectionView
iOS Development
Visible Cell Index
Swift Programming
Mobile App Development

UICollectionView current visible cell index

Interview Questions practice on Codemia

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

Browse interview questions

Introduction

Finding the current visible cell index in UICollectionView is common for analytics, autoplay behavior, and page indicators. The method you choose depends on whether you need all visible cells, the first visible cell, or the cell nearest to the viewport center. Reliable implementations account for unsorted index paths, scrolling state, and layout timing.

Core Sections

Get visible index paths

indexPathsForVisibleItems returns currently visible items, but order is not guaranteed.

swift
let visible = collectionView.indexPathsForVisibleItems
print(visible)

If you need deterministic ordering, sort by section and item.

swift
1let sorted = collectionView.indexPathsForVisibleItems.sorted {
2    if $0.section == $1.section { return $0.item < $1.item }
3    return $0.section < $1.section
4}

Determine the primary visible item

For horizontal carousels, center-based selection is usually better than first sorted index.

swift
1func centeredIndexPath(in collectionView: UICollectionView) -> IndexPath? {
2    let center = CGPoint(
3        x: collectionView.contentOffset.x + collectionView.bounds.width / 2,
4        y: collectionView.contentOffset.y + collectionView.bounds.height / 2
5    )
6    return collectionView.indexPathForItem(at: center)
7}

This aligns with what users perceive as the current card.

Track visibility during scrolling

Use scroll delegate callbacks to update UI state when visible index changes.

swift
1func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
2    guard let cv = scrollView as? UICollectionView,
3          let indexPath = centeredIndexPath(in: cv) else { return }
4    pageControl.currentPage = indexPath.item
5}

You can also update continuously in scrollViewDidScroll for dynamic effects.

Use lifecycle callbacks for precise enter and exit events

willDisplay and didEndDisplaying are useful for video autoplay, metrics, and resource management.

swift
1func collectionView(_ collectionView: UICollectionView,
2                    willDisplay cell: UICollectionViewCell,
3                    forItemAt indexPath: IndexPath) {
4    // start lightweight work
5}
6
7func collectionView(_ collectionView: UICollectionView,
8                    didEndDisplaying cell: UICollectionViewCell,
9                    forItemAt indexPath: IndexPath) {
10    // stop work, cancel requests
11}

This approach is often more reliable than polling visible items repeatedly.

Handle layout invalidation and updates

After data reloads or batch updates, visible index calculations can briefly return stale values. Perform index checks after layout passes when needed.

swift
1collectionView.performBatchUpdates({
2    // updates
3}, completion: { _ in
4    self.collectionView.layoutIfNeeded()
5    let index = self.centeredIndexPath(in: self.collectionView)
6    print(index as Any)
7})

Timing control avoids race conditions in animated updates.

Practical guidance

Pick one definition of current item and reuse it consistently across analytics, page indicators, and autoplay. Mixed definitions create hard-to-debug behavior where UI and metrics disagree.

Analytics and autoplay use case pattern

Many apps need the currently visible item for impression tracking or media autoplay. A stable pattern is to compute centered index only when scrolling settles, then emit one event if index changed.

swift
1private var lastTrackedIndex: IndexPath?
2
3func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
4    if !decelerate { trackCurrentIndex() }
5}
6
7func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
8    trackCurrentIndex()
9}
10
11private func trackCurrentIndex() {
12    guard let idx = centeredIndexPath(in: collectionView) else { return }
13    guard idx != lastTrackedIndex else { return }
14    lastTrackedIndex = idx
15    print("track impression", idx.item)
16}

This avoids duplicate events while the user is mid-scroll.

For video cells, start playback only after scroll settles and stop playback in didEndDisplaying. This keeps CPU and battery usage under control on long feeds. A clear lifecycle policy for visible cells improves both metrics accuracy and user experience.

Add UI tests for fast swipes and rotation changes so current-index logic remains stable under real user interactions.

Common Pitfalls

  • Assuming indexPathsForVisibleItems is already sorted in visual order.
  • Using first visible item when UI behavior should follow centered item.
  • Reading visible indices during layout transitions and getting stale results.
  • Forgetting to stop expensive cell work when cells leave viewport.
  • Implementing different current-index rules across app features.

Summary

  • Use indexPathsForVisibleItems for full visible set and sort when order matters.
  • Use center-point lookup for carousel-style current item behavior.
  • Update index state from scroll delegate events for responsive UI.
  • Use display lifecycle callbacks for resource-heavy cell features.
  • Keep one consistent current-index definition across the codebase.

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.