UIHostingConfiguration can cause UICollectionViewRecursion
Rotating a particular screen in one of my iPhone apps from portait to landscape resulted in a half black screen, a crash, and the following mouthful of an error being logged:
Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'UICollectionView (...) is stuck in its update/layout loop. This can
happen for various 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. In particular,
look for messages about layout invalidations, or changes to properties like
contentOffset (bounds.origin), bounds.size, frame, etc.
After quite a while of reviewing my collection view’s layout and views, and commenting out different blocks, I uncovered what’s causing the crash. It’s a combination of the following1:
- Using the new UIHostingConfiguration from iOS 16 to build collection view cells using SwiftUI.
- Using the
.frame()
modifier anywhere in those SwiftUI views. - Using a flow layout with automatic sizing enabled, and defining a
sectionInset
.
In my testing this only crashes on an iPhone, but iPad is fine.
It is rather disappointing as I switched from a pure SwiftUI-based grid view to one backed by UICollectionView, so that I can use multi-item selection on iPad, as that’s not yet available through SwiftUI.
I did not find an easy fix. Avoid setting a section inset is a quick fix, but might make achieving the layout you want harder. I will see how I go with that, or I might end up going all SwiftUI for this view on iPhone (as multi-item selection isn’t that critical for my use case there) and keep it based on UICollectionView on iPhone.
-
As confirmed in a simple sample project, and reported to Apple as FB11986452. ↩