Subclassing UICollectionViewLayoutAttributes Correctly

I had the need to create a custom UICollectionViewLayout and I also needed to subclass UICollectionViewLayoutAttributes to add a representation attribute so I could ‘tell’ each cell to draw itself differently depending on the users’ selection of a view type.

In looking at examples others had provided for subclassing UICollectionViewLayoutAttributes I found a major confusion.  Many developers are trying to use the UICollectionViewLayout’s layoutAttributesForItemAtIndexPath method as a call to create the attributes object, but that method is meant to be called by the UICollectionView to return attributes for a specific item in the collection.

The correct way to create a new instance of custom attributes is to call UICollectionViewLayoutAttributes’ layoutAttributesForCellWithIndexPath class method.  You can call this method with any subclass of UICollectionViewLayoutAttributes to create a instance of your custom attributes (you’ll notice that it has instancetype as its return value, so it returns an instance of whatever class calls the method).

So, to create an instance of my custom layout attributes, I would use:

MyCustomLayoutAttributes *layoutAttributes = [MyCustomLayoutAttributes layoutAttributesForCellWithIndexPath:someIndexPath];

However, if you want to allow your custom layout class to be subclassed and allow the layerAttributesClass method overridden, then you should ask for the current layoutAttributeClass as shown here:

UICollectionViewLayoutAttributes *layoutAttributes = [[[self class] layoutAttributesClass] layoutAttributesForCellWithIndexPath:someIndexPath];
// setup standard attribute parameters in UICollectionViewLayoutAttributes
if ([layoutAttributes isKindOfClass:[MyCustomLayoutAttributes class])
    MyCustomLayoutAttributes *myAttributes = (MyCustomLayoutAttributes*)layoutAttributes;
    // setup custom attributes