Search code examples
iosswiftuicollectionviewuicollectionviewlayout

UICollectionView - attempt to prepare a layout while a prepareLayout call was already in progress - Swift


We have a horizontal scrolling collectionView that has 2 sections.

1st section has cells that are set by array's data and the last section has only 1 cell, that says "Add new item" (which redirects to another viewcontroller)

To align all these cells, I have set up this code:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        // "Add new item" cell
        if indexPath.section == 2 {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellAdd", for: indexPath) as! AddCollectionViewCell
            let size = cell.itemText.systemLayoutSizeFitting(UIView.layoutFittingExpandedSize)
            return CGSize(width: size.width, height: 62)
        }

        if let items = accountItems {
            let cell = ItemCollectionViewCell()
            let item = items[indexPath.section].names[indexPath.row]
            cell.itemText.text = item.title
            let size = cell.itemText.systemLayoutSizeFitting(UIView.layoutFittingExpandedSize)
            return CGSize(width: size.width+30, height: 62)
        }
        
        return CGSize(width: 100, height: 62)
    }

But when code enters the if-statement (if indexPath.section == 2) in devices with iOS < 11, the app crashes.

And with the devices with iOS >= 11, warning is thrown saying:

[CollectionView] An attempt to prepare a layout while a prepareLayout call was already in progress (i.e. reentrant call) has been ignored. Please file a bug.

What are the ways to fix this warning and crash it causes on devices with iOS < 11?


Solution

  • For anyone wondering, you should not create cell in the sizeForItemAt method. Instead, to calculate the cell's width or height, I used to calculate string's size I use to populate the cells as stated here