Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Warning: UICollectionViewFlowLayout has cached frame mismatch for index path 'abc'

This is the code causing the warning:

private override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
    let attributes = super.layoutAttributesForItemAtIndexPath(indexPath)
    let distance = CGRectGetMidX(attributes!.frame) - self.midX;
    var transform = CATransform3DIdentity;
    transform = CATransform3DTranslate(transform, -distance, 0, -self.width);
    attributes!.transform3D = CATransform3DIdentity;
    return attributes
}

The console also prints:

This is likely occurring because the flow layout "xyz" is modifying attributes returned by UICollectionViewFlowLayout without copying them.

How do I fix this warning?

like image 330
Dhruv Goel Avatar asked Jul 20 '15 02:07

Dhruv Goel


3 Answers

This is likely occurring because the flow layout "xyz" is modifying attributes returned by UICollectionViewFlowLayout without copying them

And sure enough, that's just what you are doing:

private override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
    let attributes = super.layoutAttributesForItemAtIndexPath(indexPath)
    let distance = CGRectGetMidX(attributes!.frame) - self.midX;
    var transform = CATransform3DIdentity;
    transform = CATransform3DTranslate(transform, -distance, 0, -self.width);
    attributes!.transform3D = CATransform3DIdentity;
    return attributes
}

I expect that if you simply say:

let attributes = 
    super.layoutAttributesForItemAtIndexPath(indexPath).copy() 
    as! UICollectionViewLayoutAttributes

or similar, the problem will go away.

like image 85
matt Avatar answered Nov 14 '22 07:11

matt


In addition to the great answer above.

I know the example code is written in swift, but I thought that it can be helpful to have the Objective-C version.

For Objective-C, this won't work, because the copy function does only a shallow copy. You will have to do this:

NSArray * original   = [super layoutAttributesForElementsInRect:rect];
NSArray * attributes = [[NSArray alloc] initWithArray:original copyItems:YES];

I have added a temp variable for readability.

like image 43
Georgi Boyadzhiev Avatar answered Nov 14 '22 09:11

Georgi Boyadzhiev


I had this issue when overriding layoutAttributesForElementsInRect. Iterating through each element in the super.layoutAttributesForElementsInRect(rect) array and calling copy wasn't working for me, so I ended up falling back on Foundation classes and using NSArray's copyItems:

override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    // unwrap super's attributes
    guard let superArray = super.layoutAttributesForElementsInRect(rect) else { return nil }

    // copy items
    guard let attributes = NSArray(array: superArray, copyItems: true) as? [UICollectionViewLayoutAttributes] else { return nil }

    // modify attributes

    return attributes
}
like image 23
JAL Avatar answered Nov 14 '22 07:11

JAL