As @Dheeraj Agarwal points out, none of the 'ScrollTo' functionality of UICollectionView
OR UIScrollView
will seem to work properly if it is called before the view has been laid out. To be accurate, I think they WORK, but the effects are immediately nullified because laying out a UICollectionView
causes it to reset to its minimum bounds, probably because of all the cell layout functions that will trigger, and the fact its content size may change.
The solution is to make sure this function is called after layout occurs, but it's not that simple. It's entirely likely that a collection view may be told to layout its content again and again in response to various changes - setting delegates, the contents updating, the view controller being added to a parent and therefore changing size. Each time this happens it'll reset to 0:0 offset.
You'll therefore have to keep a reference to the desired offset / cell index / frame until such a time as you are CERTAIN there will be no more unexpected layout updates. You can't just nil it out immediately as your collection view's layout might change multiple times before the view appears. I'm currently storing a frame in an attribute and calling the function in layoutFrames
every time (my collection view's parent is a custom view, not a view controller). Although this has the slightly annoying feature of scrolling back again if the user rotates their phone, I consider it acceptable since this is a custom keyboard and most users will work with it in one orientation or the other, they won't keep flipping their phone around just to select a single value.
Solutions like calling DispatchQueue.main.asyncAfter
are fragile. They work because the function call gets delayed until after the first layout occurs, but this may not always-and-forever solve the problem.
I guess the 'Scroll To' functions were only ever intended to be used in response to direct user input after the collection view is already populated.