What follows is about tvOS 15 but may also apply to iOS 15.
Our app may display several types of UICollectionView cells and it depends on the content sent by our backend. Prior to tvOS 15, we used to lazily instantiate UICollectionView cell registrations when needed for the first time while building a UICollectionViewDiffableDataSource. Eventually, each cell registration is only instantiated once (or never).
Now tvOS 15 throws an exception when doing so, pretending to prevent the app from creating a new cell registration each time. And it does not care whether it's actually a new cell registration each time or one that is lazily instantiated once.
Here is the exception:
*** Assertion failure in -[UICollectionView dequeueConfiguredReusableCellWithRegistration:forIndexPath:item:], UICollectionView.m:7413
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Attempted to dequeue a cell using a registration that was created inside -collectionView:cellForItemAtIndexPath: or inside a UICollectionViewDiffableDataSource cell provider. Creating a new registration each time a cell is requested will prevent reuse and cause created cells to remain inaccessible in memory for the lifetime of the collection view. Registrations should be created up front and reused. Registration: <UICollectionViewCellRegistration: 0x6000000f8c60>'
I understand the concern but lazy instantiation is a thing and it should not be for forbidden for the sake of best practices that are not related to it. In my humble opinion, this assert should be removed and apps should be allowed to create cell registrations on the fly.
Please see further details and explanation behind this change in iOS and tvOS 15 here: https://developer.apple.com/forums/thread/681739
While lazy creation of cell registrations is no longer supported, it should be very straightforward to ensure all possible cell registrations are created up front when first loading the collection view. Each cell registration is very lightweight, and you should not see performance issues even if you have a large number of registrations.
But if you have a use case that absolutely requires lazy registration of cell types, you can still achieve this using the traditional API to register cell classes or nibs using a reuse identifier, and then dequeue cells using those identifiers.