Warning: UICollectionViewFlowLayout has cached frame mismatch for index path 'abc'
Solution 1:
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.
Solution 2:
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.
Solution 3:
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
}
Solution 4:
It's not the answer to original question, but can help for layoutAttributesForElements(in rect: CGRect) (Swift 3.0):
let safeAttributes = super.layoutAttributesForElements(in: rect)?.map { $0.copy() as! UICollectionViewLayoutAttributes }
safeAttributes?.forEach { /* do something with attributes*/ }