Philip Müller Philip Müller - 28 days ago 7
Objective-C Question

Swift app migration issue

I'm rewriting my app into Swift and everything worked fine so far. But recently I tried to translate a UICollectionViewFlowLayout subclass and I encountered some problems. I'm unable to understand how to translate the layoutAttributesForElementsInRect method of this class... I just get too many errors. The problem with this class is that it's the single one I've not written. I downloaded the class from the Internet so I don't understand the logic behind it. Can anyone help me? Here is the complete class, but I need only the layoutAttributesForElementsInRect method since I've successfully translated the second (layoutAttributesForItemAtIndexPath) one. And oh, yes! The layout basically left-aligns every cell inside the corresponding collection view! Thanks in advice!

#import "IYAlignLeftLayout.h"

const NSInteger kMaxCellSpacing = 30;

@implementation IYAlignLeftLayout

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSArray* attributesToReturn = [super layoutAttributesForElementsInRect:rect];
for (UICollectionViewLayoutAttributes* attributes in attributesToReturn) {
if (nil == attributes.representedElementKind) {
NSIndexPath* indexPath = attributes.indexPath;
attributes.frame = [self layoutAttributesForItemAtIndexPath:indexPath].frame;
}
}
return attributesToReturn;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes* currentItemAttributes =
[super layoutAttributesForItemAtIndexPath:indexPath];

UIEdgeInsets sectionInset = UIEdgeInsetsMake(50, 20, 50, 20);

if (indexPath.item == 0) { // first item of section
CGRect frame = currentItemAttributes.frame;
frame.origin.x = sectionInset.left; // first item of the section should always be left aligned
currentItemAttributes.frame = frame;

return currentItemAttributes;
}

NSIndexPath* previousIndexPath = [NSIndexPath indexPathForItem:indexPath.item-1 inSection:indexPath.section];
CGRect previousFrame = [self layoutAttributesForItemAtIndexPath:previousIndexPath].frame;
CGFloat previousFrameRightPoint = previousFrame.origin.x + previousFrame.size.width + kMaxCellSpacing;

CGRect currentFrame = currentItemAttributes.frame;
CGRect strecthedCurrentFrame = CGRectMake(0,
currentFrame.origin.y,
self.collectionView.frame.size.width,
currentFrame.size.height);

if (!CGRectIntersectsRect(previousFrame, strecthedCurrentFrame)) { // if current item is the first item on the line
// the approach here is to take the current frame, left align it to the edge of the view
// then stretch it the width of the collection view, if it intersects with the previous frame then that means it
// is on the same line, otherwise it is on it's own new line
CGRect frame = currentItemAttributes.frame;
frame.origin.x = sectionInset.left; // first item on the line should always be left aligned
currentItemAttributes.frame = frame;
return currentItemAttributes;
}

CGRect frame = currentItemAttributes.frame;
frame.origin.x = previousFrameRightPoint;
currentItemAttributes.frame = frame;
return currentItemAttributes;
}

@end

Answer

Try this code.

override func layoutAttributesForElementsInRect(rect: CGRect) -> AnyObject[]!
   {
    var attributesToReturn:UICollectionViewLayoutAttributes[] = super.layoutAttributesForElementsInRect(rect) as UICollectionViewLayoutAttributes[]

    for  attributes in attributesToReturn {

        if let elemedKind = attributes.representedElementKind {
            var indexPath: NSIndexPath  = attributes.indexPath;
            attributes.frame = self.layoutAttributesForItemAtIndexPath(indexPath).frame
        }
    }
    return attributesToReturn;
   }