I get this error when I try to update my collectionView layout on iOS 14: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSDictionaryM setObject:forKey:]: object cannot be nil (key: <NSIndexPath: 0x9f9aa264ee754972> {length = 2, path = 0 - 0})'

However it works absolutely fine on iOS 16! Even on another view controller it works fine with iOS 14.

collectionView.setCollectionViewLayout(mode.layout, animated: false)

extension ItemsViewMode {
    var layout: UICollectionViewFlowLayout {
        switch self {
        case .card:
            return OfferingCardLayout()
        case .investmentCard:
            return InvestmentsCardLayout()
        case .list:
            return OfferingListLayout()
        case .investmentList:
            return InvestmentsListLayout()
        }
    }
  }
class InvestmentsListLayout: OfferingListLayout {
    private enum Const {
        static let itemHeight: CGFloat = 164
        static let minimumLineSpacing: CGFloat = 16
    }

    override init() {
        super.init()
        itemHeight = Const.itemHeight
        minimumLineSpacing = Const.minimumLineSpacing
    }
}

class OfferingListLayout: UICollectionViewFlowLayout {
    private enum Const {
        static let minimumInteritemSpacing: CGFloat = 0
        static let minimumLineSpacing: CGFloat = 2
        static let leftRightSpacing: CGFloat = 8
        static let itemHeight: CGFloat = 216
    }

    var itemHeight: CGFloat = Const.itemHeight

    override init() {
        super.init()
        register(SeparatorView.self, forDecorationViewOfKind: "separator")
        scrollDirection = .vertical
        minimumInteritemSpacing = Const.minimumInteritemSpacing
        minimumLineSpacing = Const.minimumLineSpacing
        footerReferenceSize = CGSize(width: 50, height: 50)
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func prepare() {
        guard let collectionView = collectionView, collectionView.numberOfSections > 0 else { return }

        itemSize = CGSize(width: collectionView.frame.width - Const.leftRightSpacing * 2, height: itemHeight)
        super.prepare()
    }

    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        true
    }

    override func invalidationContext(forBoundsChange newBounds: CGRect) -> UICollectionViewLayoutInvalidationContext {
        guard let context = super.invalidationContext(forBoundsChange: newBounds) as? UICollectionViewFlowLayoutInvalidationContext else {
            return UICollectionViewLayoutInvalidationContext()
        }
        context.invalidateFlowLayoutDelegateMetrics = newBounds.size != collectionView?.bounds.size
        return context
    }

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes] {
        let layoutAttributes = super.layoutAttributesForElements(in: rect) ?? []
        let lineWidth: CGFloat = Const.minimumLineSpacing
        var decorationAttributes: [UICollectionViewLayoutAttributes] = []

        // skip first cell
        for layoutAttribute in layoutAttributes where layoutAttribute.indexPath.item > 0 {
            let separatorAttribute = UICollectionViewLayoutAttributes(forDecorationViewOfKind: "separator", with: layoutAttribute.indexPath)
            let cellFrame = layoutAttribute.frame
            separatorAttribute.frame = CGRect(x: cellFrame.origin.x, y: cellFrame.origin.y - lineWidth, width: cellFrame.size.width, height: lineWidth)
            separatorAttribute.zIndex = Int.max
            decorationAttributes.append(separatorAttribute)
        }

        return layoutAttributes + decorationAttributes
    }
}

I even tried setting breakpoints here but no luck.

1

There are 1 best solutions below

0
Omair Ahmed On

I implemented the following function in my layout class and it works fine now:

override func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        nil
}