11

I'm implementing a custom flow layout. It has 2 main methods for overriding to determine placement of cells: layoutAttributesForElementsInRect and layoutAttributesForItemAtIndexPath.

In my code, layoutAttributesForElementsInRect is called, but layoutAttributesForItemAtIndexPath isn't. What determines which gets called? Where does layoutAttributesForItemAtIndexPath get called?

Alaeddine
  • 6,104
  • 3
  • 28
  • 45
Gaurav Sharma
  • 2,680
  • 3
  • 26
  • 36

1 Answers1

22

layoutAttributesForElementsInRect: doesn't necessarily call layoutAttributesForItemAtIndexPath:.

In fact, if you subclass UICollectionViewFlowLayout, the flow layout will prepare the layout and cache the resulting attributes. So, when layoutAttributesForElementsInRect: is called, it won't ask layoutAttributesForItemAtIndexPath:, but just uses the cached values.

If you want to ensure that the layout attributes are always modified according to your layout, implement a modifier for both layoutAttributesForElementsInRect: and layoutAttributesForItemAtIndexPath::

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
  NSArray *attributesInRect = [super layoutAttributesForElementsInRect:rect];
  for (UICollectionViewLayoutAttributes *cellAttributes in attributesInRect) {
    [self modifyLayoutAttributes:cellAttributes];
  }
  return attributesInRect;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
  UICollectionViewLayoutAttributes *attributes = [super layoutAttributesForItemAtIndexPath:indexPath];
  [self modifyLayoutAttributes:attributes];
  return attributes;
}

- (void)modifyLayoutAttributes:(UICollectionViewLayoutAttributes *)attributes
{
  // Adjust the standard properties size, center, transform etc.
  // Or subclass UICollectionViewLayoutAttributes and add additional attributes.
  // Note, that a subclass will require you to override copyWithZone and isEqual.
  // And you'll need to tell your layout to use your subclass in +(Class)layoutAttributesClass
}
Robert
  • 1,936
  • 27
  • 38
  • What if I need the index path to determine the rect property of the attribute? I have no way of passing the index path into the modify function. – sudo Jun 03 '15 at 23:45
  • 3
    A `UICollectionViewLayoutAttributes` has the `indexPath` property. – Robert Jun 03 '15 at 23:50
  • @Robert Doesn't [super layoutAttributesForElementsInRect] return nil? That's the impression I got from the APple docs. –  Aug 17 '15 at 19:30
  • 4
    @moonman239 `[super layoutAttributesForElementsInRect]` returns valid layout attributes when used on a subclass of `UICollectionViewFlowLayout`. It returns `nil` when used on a custom subclass of `UICollectionViewLayout`. If you write your own layout based on `UICollectionViewLayout` you can create blank layout attributes using `[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:]`. – Robert Aug 17 '15 at 19:56