UICollectionView scrollToItem broken on iOS14

Hi all,

since iOS 14, UICollectionView's scrollToItem(at:at:animated:) method is broken under certain circumstances.

The setup


I'm using UICollectionViewCompositionalLayout to define two sections. The first section scrolls horizontally and also has a section header configured:

Code Block swift
section.orthogonalScrollingBehavior = .paging
let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(44)), elementKind: "header", alignment: .top)
section.boundarySupplementaryItems = [header]


The behavior


Depending on different settings for section.orthogonalScrollingBehavior I observe the following:

scrollToItem
  • does not work if orthogonalScrollingBehavior is .paging, .groupPaging, .groupPagingCentered

  • does work if orthogonalScrollingBehavior is .continuous or .continuousGroupLeadingBoundary

  • does work if I don't add the header to the section ✅

  • does work if the header's height is .absolute(0)

  • does work if the header's alignment is .bottom (i.e. if the section's boundarySupplementaryItem is a footer instead of a header) ✅

=> As soon as there's a view taking up vertical space before the section scrollToItem does not work (if supplied with an IndexPath for that particular section)

Anyone any ideas what might cause this? There's no problem on iOS 13.x.
Same problem here. I made onboarding screen using collection view without any supplementary items with orthogonalScrollingBehavior = .groupPagingCentered, and scrollToItem(at:at:animated:) doesn't work on iOS 14, but works fine on iOS 13. Thanks for temporary solution with .continuousGroupLeadingBoundary, but I hope it would be fixed in iOS 14.1+
Same here. I hope it gets fixed soon.
iOS 14.1 does not fix it.
Since iOS 14.1 does not fix it, I am sharing a work around solution that I am using.
  1. create a boolean flag and set orthogonalScrollingBehavior as following:

Code Block swift
orthogonalScrollingBehavior = flag ? .continuousGroupLeadingBoundary : .groupPagingCentered


2. call scrollToItem like this:
Code Block swift
flag = true
collectionView.collectionViewLayout.invalidateLayout()
collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: false)
flag = false
collectionView.collectionViewLayout.invalidateLayout()

Still the same on iOS 14.2
Hi, i had a same issue with collection view on iOS 14 and i found out, if you have paging enabled on your collection view, method scrollToItem will do nothing. Workaround for this is to set paging on false before this method and then turn it back to true.

self.collectionView.isPagingEnabled = false
self.collectionView.scrollToItem(at: indexPath, at: .left, animated: false)
self.collectionView.isPagingEnabled = true

This is temporary solution for this bug on iOS14. Hope this will help someone and save their time :)
16
self.collectionView.layoutIfNeeded()
self.collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: false)

Solve the problem for me.
Is this fixed in 14.4? Is this bug found on iOS only? Is it applied to tvOS as well?
Not fixed in 14.4
Not fixed in 14.5 RC
Not fixed iOS 14.5, Xcode 12.5.

I use this behavior until fix:

self.collectionView.isPagingEnabled = false
self.collectionView.scrollToItem(at: indexPath, at: .left, animated: false)
self.collectionView.isPagingEnabled = true
Hi All

Where we have to put this code?

self.collectionView.isPagingEnabled = false
self.collectionView.scrollToItem(at: indexPath, at: .left, animated: false)
self.collectionView.isPagingEnabled = true


In my scenario, Let's suppose there are 5 items to show in Collection View Horizontally and we navigate to another screen, where we make some setting change. Due to this server response will change.

When we come back on Collection View Screen and make api call for getting updated data but collection views are not updating. It's show old cell and due to this app gets crash, because we are getting updated data from server.

I called colletionview.reloadData() when get response from server and inside collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) method getting indexPath.row value old one and not updated.

This problem is only on iOS 14.5 version. On old versions app working fine.

Thanks
Gaurav




Seems to be fixed for me with iOS 15 SDK (Xcode 13 required).

Moreover, it's started to work on iOS 14 too (tested on iOS 14.5 Simulator for iPad Pro 9.7 inch, iPhone 8, iPhone 11). I recommend to test this issue again on Xcode 13 and remove workarounds if it works for you too.

This worked for me. didEndDisplaying denotes collectionView is now ready to scroll

firstTimeScrollClosure = {
    collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: false)
}

func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        firstTimeScrollClosure?()
        firstTimeScrollClosure = nil
}

For anyone who encounter this issue and if you are using UICollectionViewCompositionalLayout. It seems you can't set both the collectionView's isPageEnabled = true and the UICollectionViewCompositionalLayout's orthogonalScrollingBehavior = .groupPaging.

I keep only orthogonalScrollingBehavior = .groupPaging (or .paging any scenario you want), and set collectionView's isPageEnabled = false. Then the scroll to item issue will be gone.

UICollectionView scrollToItem broken on iOS14
 
 
Q