UICollectionViewRecursion when using estimated sizes in Compositional Layout

Hi everyone,

our team was transferred a project that is using a "UICollectionViewCompositionalLayout" for displaying a large amount of data.

On iOS 14 and below, we seemed to be having no problems. Now on iOS 15 however, we keep getting this debugger message:

APPNAME[47924:507017] [UICollectionViewRecursion] cv == 0x7ff2af9d0200 Disabling recursion trigger logging

We are also collecting crashes in our crash tool, solely from iOS 15 devices, saying:

NSInternalInconsistencyException: UICollectionView (<UICollectionView 0x1122a6400>) is stuck in its update/layout loop. This can happen for many reasons, including self-sizing views whose preferred attributes are not returning a consistent size. To debug this issue, check the Console app for logs in the "UICollectionViewRecursion" category.

We've found that setting all .estimated() sizes we're using in the section provider to .absolute() gets rid of the message, but of course the views aren't sized correctly then.

We are using views that size themselves based on the content they display, using UIStackViews. We need them to be dynamic in height.

Has something changed moving from iOS 14 to 15 about how the compositional layout has to be configured? Is there something we can do to further debug this issue?

I've found some questions about this asked on StackOverflow, but none of them were answered either.

We're having a very similar issue with our self-sizing cells on iOS 15.

We're having the same problem.

I downloaded Xcode 13.2 Beta and I no longer get the UICollectionViewRecursion warnings in the iOS 15.2 simulator - though still get them on iOS 15.0. I looks to me to be a bug/regression in iOS 15 that's since been fixed. I'm afraid it doesn't help much until 15.2 is out of beta and most users have upgraded to it.

This is getting quite specific to our particular implementation, but I believe we've found a workaround for our crash and thought I'd share in case it is of some use.

Our workaround is using floor on some of our computed values (e.g. the width of some layout attributes). My pet theory is that the bug is related to some floating point precision issue, or possibly some rounding occurring elsewhere.

This doesn't actually remove the warnings, but were able to reproduce the crash on one of our test devices and use that to confirm the workaround works. We're going to ship it and see if we stop getting crash reports in the wild.

I was also able to force the crash to happen by using floor in one place but not another. E.g. in our case, the collectionView proposes layout attributes, the cell accepts the width and computes the height it requires - if I return a different width than the one proposed then I can force the crash to happen on any simulator/device running iOS 15. FWIW just before the crash, I got: Enabling recursion trigger logging (rather than the usual Disabling).

Hope this information helps others resolve their specific issues.

Facing same issue for self sizing collection view in iOS 15

@deepa.bhat @C24QDRS I am still facing the issue despite using floor, any other workarounds or pointers did you find?

This is infuriatingly random. I have 3 super similar layout implementations in the same app. Two are working and 3rd is crashing when I pull down long enough down so that header is near the center. This causes layout loop in cells just outside the bottom edge. Those are cells where text in label is long enough taht it needs two lines.

This crashes:

func createSection(at index: Int) -> NSCollectionLayoutSection {

	let item = NSCollectionLayoutItem(

		layoutSize: NSCollectionLayoutSize(

			widthDimension: .fractionalWidth(1.0),

			heightDimension: .estimated(60)

		)

	)

	let group = NSCollectionLayoutGroup.vertical(

		layoutSize: NSCollectionLayoutSize(

			widthDimension: .fractionalWidth(1.0),

			heightDimension: .estimated(60)

		),

		subitems: [item]

	)



	let section = NSCollectionLayoutSection(group: group)



	let headerElement = NSCollectionLayoutBoundarySupplementaryItem(

		layoutSize: NSCollectionLayoutSize(

			widthDimension: .fractionalWidth(1.0),

			heightDimension: .estimated(200)

		),

		elementKind: ProfileHeaderCell.kind,

		alignment: .top

	)

	section.boundarySupplementaryItems = [headerElement]



	return section

}

but if I change the item's height to heightDimension: .fractionalHeight(1.0) then it does not crash.

With crashing code, I also noticed that lower cells are being continually extended in height as I pull the scroll view upwards. It's like I am extruding the cells. Super weird behavior.

I managed to fix that by updating collection cell row. Since I was giving height and width for each cell item in NSCollectionLayoutSection, I just centered the content instead of giving top and bottom constraints

UICollectionViewRecursion when using estimated sizes in Compositional Layout
 
 
Q