Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

ios

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.

like image 883
Frank Avatar asked Jun 12 '15 20:06

Frank


People also ask

How do I know that the Uicollectionview has been loaded completely?

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

What is swift Uicollectionview?

An object that manages an ordered collection of data items and presents them using customizable layouts.


2 Answers

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) }
like image 90
Ben Avatar answered Sep 30 '22 20:09

Ben


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.

like image 20
Erakk Avatar answered Sep 30 '22 19:09

Erakk