After calling -[UICollectionView reloadData]
it takes some time for cells to be displayed, so selecting an item immediately after calling reloadData
does not work. Is there a way to select an item immediately after reloadData
?

- 18,392
- 8
- 66
- 81

- 985
- 3
- 9
- 19
-
Any updates on this? I've got the same problem, trying to create a selection during UICollectionView load. – Mark Ingram Mar 14 '13 at 15:09
9 Answers
Along the lines of this answer I found that calling layoutIfNeeded
after reloadData
seemed to effectively 'flush' the reload before I do other things to the collectionView:
[self.collectionView reloadData];
[self.collectionView layoutIfNeeded];
...
On the page I found this solution, some commenters indicated it didn't work for them on iOS 9, but it's been fine for me so your mileage may vary.

- 1
- 1

- 4,399
- 37
- 44
The Swift way:
let selected = collectionView.indexPathsForSelectedItems()
collectionView.performBatchUpdates({ [weak self] in
self?.collectionView.reloadSections(NSIndexSet(index: 0))
}) { completed -> Void in
selected?.forEach { [weak self] indexPath in
self?.collectionView.selectItemAtIndexPath(indexPath, animated: false, scrollPosition: [])
}
}

- 74,769
- 26
- 128
- 150

- 2,276
- 1
- 16
- 24
I'm handling selection of cells in collectionView: cellForItemAtIndexPath:
. The problem I found was that if the cell didn't exist, simply calling selectItemAtIndexPath: animated: scrollPosition:
wouldn't actually select the item.
Instead you have to do:
cell.selected = YES;
[m_collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];

- 71,849
- 51
- 176
- 230
Don't use reloadData
Use - (void)performBatchUpdates:(void (^)(void))updates completion:(void (^)(BOOL finished))completion
instead. The completion block is executed after animations for cell insertion/deletion etc. have completed. You can put the call to reloadData in the (void (^)(void))updates
block

- 3,585
- 1
- 18
- 20
-
When the UICollectionView has lots of items, I've seen HUGE performance problems with the animated update calls vs. reloadData. – Eric Sink Jul 11 '13 at 16:37
Apple says:
You should not call this method in the middle of animation blocks where items are being inserted or deleted. Insertions and deletions automatically cause the table’s data to be updated appropriately.
In fact, you should not call this method in the middle of any animation (including UICollectionView
in the scrolling).
So, you can use:
[self.collectionView setContentOffset:CGPointZero animated:NO];
[self.collectionView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
or mark sure not any animation, and then call reloadData
;
or
[self.collectionView performBatchUpdates:^{
//insert, delete, reload, or move operations
} completion:nil];
Hope this is helpful to you.
Make sure you're calling reloadData
on the main thread. That could be the cause for the delay in your cell updates.

- 9,731
- 1
- 31
- 35
-
And [the answer to this question](http://stackoverflow.com/questions/14804359/uicollectionview-doesnt-update-immediately-when-calling-reloaddata-but-randoml) shows how to do that. – Jeff Apr 10 '13 at 23:54
I handled it on the willDisplayCell colelctionView delegate. The idea: A temp variable is needed to specify the initial scrolling has performed already or not (scrollIsRequired). When the last visible cell will display, than we can scroll to the required cell and set this variable to avoid scrolling again.
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{
//Perform any configuration
if (CGRectGetMaxX(collectionView.frame) <= CGRectGetMaxX(cell.frame)) {
// Last visible cell
if (self.scrollIsRequired) {
[self.collectionView selectItemAtIndexPath:[NSIndexPath indexPathForItem:self.initiallySelectedRepresentativeVerse inSection:0] animated:YES scrollPosition:UICollectionViewScrollPositionLeft];
self.scrollIsRequired = NO;
}
}
}
It has worked for me like a charm.

- 2,333
- 19
- 29
This is what worked for me:
I kept a reference of the selected index path and overide the reloadData function:
override func reloadData() {
super.reloadData()
self.selectItem(at: self.selectedIndexPath, animated: false, scrollPosition: UICollectionViewScrollPosition())
}
I tried doing it using indexPathForSelectedItems, but it was creating an infinite loop on collection view load.

- 9,971
- 5
- 32
- 38
create a method that does the selection and call it using performSelector after calling reload e.g;
[self performSelector:@selector(selectIt) withObject:self afterDelay:0.1];

- 1,900
- 1
- 12
- 15
-
I dislike this solution because it requires an arbitrary amount of time. How would we know when ```reloadData``` is done? It seems there's no way to query this. – mjh Mar 01 '13 at 03:05