On a collection view, i would like to know the first item that's being displayed on the collection view. I figured I would look at visibleCells and would be the first item on the list, but it's not the case.
Simply reload collectionView inside batch updates and then check in the completion block whether it is finished or not with the help of boolean "finish".
An object that manages an ordered collection of data items and presents them using customizable layouts.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With