My code
extension MyViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(
_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath
) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: "CollectionViewCellID",
for: indexPath
) as? CollectionViewCell {
cell.setup()
return cell
}
return UICollectionViewCell()
}
func collectionView(
_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath
) {
// Unnecessary dequeue
guard collectionView.dequeueReusableCell(
withReuseIdentifier: "CollectionViewCellID",
for: indexPath
) is CollectionViewCell else { return }
// My action for selecting cell
print("Cell Selected")
}
}
Error:
*** Assertion failure in -[UICollectionView _updateVisibleCellsNow:], UICollectionView.m:5673
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Expected dequeued view to be returned to the collection view in preparation for display. When the collection view's data source is asked to provide a view for a given index path, ensure that a single view is dequeued and returned to the collection view. Avoid dequeuing views without a request from the collection view. For retrieving an existing view in the collection view, use -[UICollectionView cellForItemAtIndexPath:] or -[UICollectionView supplementaryViewForElementKind:atIndexPath:].
Solution:
The problem was doing unnecessary dequeuing in didSelectItemAt
when selecting the cell. In previous iOS like 17 or 16 or lower, it was allowed to dequeue where it is not really needed but from iOS 18, it may restricted to unnecessary dequeuing. So better to remove dequeue and use cellForItem(at) if we need to get cell from collection view.
Example
extension MyViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(
_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath
) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: "CollectionViewCellID",
for: indexPath
) as? CollectionViewCell {
cell.setup()
return cell
}
return UICollectionViewCell()
}
func collectionView(
_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath
) {
guard collectionView.cellForItem(at: indexPath) is CollectionViewCell else { return }
// My action for selecting cell
print("Cell Selected")
}
}