I was able to get this working by using the indices slightly differently:
@interface NSIndexPath (SGBGridLayout)
+ (NSIndexPath *)indexPathForGridSection:(NSInteger)gridSection gridRow:(NSInteger)gridRow gridColumn:(NSInteger)gridColumn numberOfColumns:(NSUInteger)numberOfColumns;
@property (nonatomic, assign, readonly) NSInteger gridSection;
@property (nonatomic, assign, readonly) NSInteger gridRow;
@property (nonatomic, assign, readonly) NSInteger gridColumn;
@property (nonatomic, assign, readonly) NSInteger itemNumber;
@property (nonatomic, assign, readonly) NSInteger numberOfColumns;
@end
@implementation NSIndexPath (SGBGridLayout)
+ (NSIndexPath *)indexPathForGridSection:(NSInteger)gridSection gridRow:(NSInteger)gridRow gridColumn:(NSInteger)gridColumn numberOfColumns:(NSUInteger)numberOfColumns
{
NSUInteger itemNumber = (gridRow * numberOfColumns) + gridColumn;
NSUInteger indexes[] = { gridSection, itemNumber, numberOfColumns };
return [self indexPathWithIndexes:indexes length:3];
}
- (NSInteger)gridSection
{
return [self indexAtPosition:0];
}
- (NSInteger)itemNumber
{
return [self indexAtPosition:1];
}
- (NSInteger)numberOfColumns
{
return [self indexAtPosition:2];
}
- (NSInteger)gridRow
{
return self.itemNumber / self.numberOfColumns;
}
- (NSInteger)gridColumn
{
return self.itemNumber % self.numberOfColumns;
}
@end
The collection view only uses the first two indices, so as long as we make sure the first two indices are always unique we can still use the third one to encode the information we need. In this case, I needed to have a section and a row/column, so I used the second to store (row * numberOfColumns) + column, and the third to store numberOfColumns; that way I can get the row and column back out when the collection view returns the index path to me.