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

前端 未结 7 1234
心在旅途
心在旅途 2020-12-01 12:19

This is the code causing the warning:

private override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes         


        
相关标签:
7条回答
  • 2020-12-01 12:24

    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
    }
    
    0 讨论(0)
  • 2020-12-01 12:30

    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*/ }
    
    0 讨论(0)
  • 2020-12-01 12:36

    Updated response for Swift 3!

    for func layoutAttributesForElements

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    
        guard let attributes = super.layoutAttributesForElements(in: rect) else {
            return nil
        }
    
        guard let attributesToReturn =  attributes.map( { $0.copy() }) as? [UICollectionViewLayoutAttributes] else {
            return nil
        }
    
        return attributesToReturn
    
    }
    

    for func layoutAttributesForItem

    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
    
        guard let currentItemAttributes = super.layoutAttributesForItem(at: indexPath)?.copy() as? UICollectionViewLayoutAttributes else {
            return nil
        }
    
        return currentItemAttributes
    }
    

    If you override both function, you have to call copy on both function!

    Good coding!

    0 讨论(0)
  • 2020-12-01 12:39

    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.

    0 讨论(0)
  • 2020-12-01 12:40

    I have subclassed UICollectionViewFlowLayout. Inside layoutAttributesForElementsInRect() I did this change:

    change from

    guard let attributesForItem: UICollectionViewLayoutAttributes = self.layoutAttributesForItemAtIndexPath(indexPath) else {
        return
    }
    

    change to

    guard let attributesForItem = self.layoutAttributesForItemAtIndexPath(indexPath)?.copy() as? UICollectionViewLayoutAttributes else {
        return
    }
    
    0 讨论(0)
  • 2020-12-01 12:47

    Adding to @Georgi answer

    <NSCopying> must be conformed and add copy message call to layoutAttributesForItemAtIndexPath

    UICollectionViewLayoutAttributes* attributes = [[super layoutAttributesForItemAtIndexPath:indexPath] copy];
    
    0 讨论(0)
提交回复
热议问题