I am trying to customise the positions of the headers in a UICollectionView using a subclassed UICollectionViewFlowLayout class (based loosely on the code for stacked headers which is shown enter link description here).
As a minimal test, let's say I just want to add a fixed offset to the position of all headers:
- I add all headers to the array returned by
layoutAttributesForElementsInRectso that all are always processed (this may be the cause of the problem, I'm not sure) - I then update each header by adding a fixed offset in
layoutAttributesForSupplementaryViewOfKind
The full implementation is included at the end of this post.
(By the way, I know that adding all headers, including those outside the rect, is not strictly speaking necessary in the first step, but this is a simplified example of a more complex customisation in position I want to make which would cause all headers to be displayed in the draw rect.)
However, when I run the code I get the following NSInternalInconsistencyException:
2014-01-15 00:41:50.130 CollectionStackedHeaders[60777:70b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'layout attributes for supplementary item at index path (<NSIndexPath: 0x8a7db90> {length = 2, path = 0 - 0}) changed from <UICollectionViewLayoutAttributes: 0x8a7f8b0> index path: (<NSIndexPath: 0x8a7d9c0> {length = 2, path = 0 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 0; 320 50); to <UICollectionViewLayoutAttributes: 0x8a7fb80> index path: (<NSIndexPath: 0x8a7db90> {length = 2, path = 0 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 50; 320 50); zIndex = 1024; without invalidating the layout' It seems that this is caused by the update of the attributes, as if I comment out the following two lines it works fine:
attributes.zIndex = 1024; attributes.frame = frame; What is causing this error, and what can I do to get my simple example up and running?
Here is the full class implementation for this simple example:
@implementation myStackedHeaderFlowLayout - (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect { // Call super to get elements NSMutableArray* answer = [[super layoutAttributesForElementsInRect:rect] mutableCopy]; // As a test, always add first header to the answer array NSArray* indexes = [NSArray arrayWithObjects: [NSNumber numberWithInt:0], nil]; for (NSNumber* sectionNumber in indexes) { NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:[sectionNumber integerValue]]; UICollectionViewLayoutAttributes* layoutAttributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath]; if (layoutAttributes) { [answer removeObject:layoutAttributes]; // remove if already present [answer addObject:layoutAttributes]; } } return answer; } - (UICollectionViewLayoutAttributes*)layoutAttributesForSupplementaryViewOfKind:(NSString*)kind atIndexPath:(NSIndexPath*)indexPath { // Call super to get base attributes UICollectionViewLayoutAttributes* attributes = [super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath]; if ([kind isEqualToString:UICollectionElementKindSectionHeader]) { CGRect frame = attributes.frame; frame.origin.y += 50; // Update attributes position here - causes the problem attributes.zIndex = 1024; attributes.frame = frame; } return attributes; } - (UICollectionViewLayoutAttributes*)initialLayoutAttributesForAppearingSupplementaryElementOfKind:(NSString*)kind atIndexPath:(NSIndexPath*)indexPath { UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath]; return attributes; } - (UICollectionViewLayoutAttributes*)finalLayoutAttributesForDisappearingSupplementaryElementOfKind:(NSString*)kind atIndexPath:(NSIndexPath*)indexPath { UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath]; return attributes; } - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBound { return YES; } @end