I'm using diffable data sources with compositional layout. The sections in my collection view can fetch their own items and in parallel, so at any point in time, my section snapshot may contain data models for a loading, success, or failure state. When a fetch results into a failure, I want the fetching section to be hidden.
To delete the section, I get a copy of my data source's current snapshot, call deleteSections(_:)
on it, and then apply the copy with apply(_:to:)
.
From my logs, it seems that calling apply(_:to:)
triggers a layout pass on the collection view, and the collection view behaves as intended when, inside UICollectionViewCompositionalLayoutSectionProvider
, I return a garbage NSCollectionLayoutSection
for a deleted section. The garbage layout is ultimately not rendered because the section is deleted from the diffable data source.
However, when I return nil from within UICollectionViewCompositionalLayoutSectionProvider
(reasonable, because the return type is optional), the app crashes with the following message at the code where apply(_:to:)
is called:
Invalid section definition. Please specify a valid section definition when content is to be rendered for a section. This is a client error.
I inspected my diffable data source's section identifiers and the section is actually in the snapshot copy prior to being deleted and the application of the copy. The console also logs the location of the assertion failure:
Assertion failure in -[_UICollectionCompositionalLayoutSolver _queryClientForSectionDefinitionForSectionIndex:], _UICollectionCompositionalLayoutSolver.m:2927
Therefore, it seems that the problem lies in the compositional layout and not in my concurrent fetches nor the operations conducted on the diffable data source.
So is it really just the case that I cannot return nil
from UICollectionViewCompositionalLayoutSectionProvider
? Because the return type is optional, and it is not anywhere in Apple documentation that I cannot return nil from it.
Hi, it is invalid to return a nil layout section if your data source also has content for that section, i.e.; numberOfItemsInSection > 0. The layout pass that you're seeing that triggers your section provider to execute with the old (pre-delete) section counts should not be occurring from iOS 15 onwards. If you're still seeing this problem on iOS 15 or higher, please do file a feedback with a sample and I'd be happy to take a look at it!