Is there a way to determine the order of the self.collectionview.visiblecells?

Updated for Swift5

let visibleCells = self.collectionView.indexPathsForVisibleItems
        .sorted { left, right -> Bool in
            return left.section < right.section || left.row < right.row
        }
        .compactMap { [weak self] in indexPath -> UICollectionViewCell? in
            return self?.collectionView.cellForItem(at: indexPath)
        }

Please note that any self in closure would keep a strong reference if not weaken.

let visibleCells = self.collectionView.indexPathsForVisibleItems
        .sorted { $0.section < $1.section || $0.row < $1.row }
        .flatMap { [weak self] in self?.collectionView.cellForItem(at: $0) }

Swift3

Based on previous answer, here is a Swift3 equivalent to get ordered visible cells, first ordering visible indexpath, then fetching UICollectionViewCell using sorted and flatMap.

let visibleCells = self.collectionView.indexPathsForVisibleItems
    .sorted { left, right -> Bool in
        return left.section < right.section || left.row < right.row
    }.flatMap { [weak self] in indexPath -> UICollectionViewCell? in
        return self?.collectionView.cellForItem(at: indexPath)
    }

In an even more simplified version, a bit less readable

let visibleCells = self.collectionView.indexPathsForVisibleItems
    .sorted { $0.section < $1.section || $0.row < $1.row }
    .flatMap { [weak self] in self?.collectionView.cellForItem(at: $0) }

Returning the first item visible on the collectionView:

UICollectionViewCell *cell = [self.collectionView.visibleCells firstObject];

returning the first item from all the items in the collectionView

UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];

You don't want the cell, just the data:

NSIndexPath *indexPath = [[self.collectionView indexPathsForVisibleItems] firstObject];
id yourData = self.dataSource[indexPath.row];

But the visivleCells array is not ordered!!

Well, then you need to order it:

NSArray *indexPaths = [self.collectionView indexPathsForVisibleItems];
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"row" ascending:YES];

NSArray *orderedIndexPaths = [indexPaths sortedArrayUsingDescriptors:@[sort]];
// orderedIndexPaths[0] would return the position of the first cell.
// you can get a cell with it or the data from your dataSource by accessing .row

Edit: i do believe the visibleCells (and the like) return ordered already, but i didn't find anything regarding this on the docs. so i added the ordering part just to make sure.

Tags:

Ios