Problem
I'd like to make a UICollectionView do an animated scroll to a specific item.
This works most of the time, but occasionally the item that I'm trying to scroll to doesn't end up being shown.
Code
- (void)onClick {
// (Possibly recompute the _items array.)
NSInteger target_idx = // (...some valid index of _items)
NSIndexPath *item_idx = [NSIndexPath indexPathForItem:target_idx inSection:0];
[self scrollToItem:item_idx];
}
- (void)scrollToItem:(NSIndexPath*)item_idx {
// Make sure our view is up-to-date with the data we want to show.
NSInteger num_items = [self.collection_view numberOfItemsInSection:0];
if (num_items != _items.count) {
[self.collection_view reloadData];
}
[self.collection_view
scrollToItemAtIndexPath:item_idx
atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally
animated:YES];
}
Details
self.collection_viewis a UICollectionView that consists of a single row of items, with a standard flow layout and horizontal scrolling enabled.- I need to call
reloadDatabefore scrolling, because it's possible that_itemshas changed since the UICollectionView last displayed it. - The problem only happens with animated scrolling; if I pass
animated:NOthen everything works as expected. - When the problem happens, a post-scroll call to
indexPathsForVisibleItemsreveals that the UICollectionView doesn't think that the target item is visible.
Any ideas why scrolling to an item silently fails sometimes?
Update: the problem seems to come from reloading and scrolling in quick succession; if there is no reload, scrolling behaves as expected. Are there any idioms for scrolling to an item after loading new data?
reloadData) and as a result I want to scroll to a new item (because I have new data). If I don't reload, I might scroll to an invalid index, possibly causing a crash. Scrolling after reloading seems like a pattern that should be fairly common, but perhaps not? - Nate KohlreloadData. So the question becomes: how can we combine reloading with scrolling? I tried reloading, asynchronously waiting, then scrolling, but the problem persists. Maybe there is someinvalidatecall that I'm missing? - Nate Kohl