UICollectionView 自定义流布局在滚动时崩溃

Posted

技术标签:

【中文标题】UICollectionView 自定义流布局在滚动时崩溃【英文标题】:UICollectionView custom flow layout crashes on scrolling 【发布时间】:2016-07-01 13:38:08 【问题描述】:

我正在创建带有节标题的自定义 flowLayout。

这是我的 flowLayout.swift

import UIKit

class FlowLayout: UICollectionViewFlowLayout 

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? 
       // let attributesForElementsInRect = super.
        var newAttributesForElementsInRect = [UICollectionViewLayoutAttributes]()

        // unwrap super's attributes
        guard let attributesForElementsInRect = super.layoutAttributesForElementsInRect(rect) else  return nil 

        // modify attributes

        var leftMargin: CGFloat = 0.0;



        for attributes in attributesForElementsInRect 

            let itemAttributesCopy = attributes.copy() as! UICollectionViewLayoutAttributes

            if( itemAttributesCopy.frame.size.width + leftMargin > self.collectionView?.frame.size.width)
            
                leftMargin = 8.0
            
            if (itemAttributesCopy.frame.origin.x == self.sectionInset.left) 
                leftMargin = self.sectionInset.left
             else 
                var newLeftAlignedFrame = itemAttributesCopy.frame
                newLeftAlignedFrame.origin.x = leftMargin
                itemAttributesCopy.frame = newLeftAlignedFrame
            
            leftMargin += itemAttributesCopy.frame.size.width + 8
            print(itemAttributesCopy.frame)

             newAttributesForElementsInRect.append(itemAttributesCopy)
            print(itemAttributesCopy)
        

        return newAttributesForElementsInRect
    


这是我的 ViewController,带有节标题的委托功能

func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int 


        if(sectionsArray.count == 0)
        
            return 1
        
        else
        
            return sectionsArray.count
        
    


     func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView 

            let headerView: TagHeader = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "TagHeader", forIndexPath: indexPath) as! TagHeader

            headerView.sectionLabel.text = sectionsArray[indexPath.section].header
            return headerView
        

所以当我运行应用程序时,它会显示部分标题,一切正常。

但是当我滚动时,应用程序崩溃并出现以下来自调试器的错误

2016-07-01 18:52:12.051 TagFlowLayout[15025:4704387] *** Assertion failure in -[UICollectionViewData validateLayoutInRect:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3512.60.7/UICollectionViewData.m:408
2016-07-01 18:52:12.054 TagFlowLayout[15025:4704387] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'layout attributes for supplementary item at index path (<NSIndexPath: 0x17e96f70> length = 2, path = 0 - 0) changed from <UICollectionViewLayoutAttributes: 0x17e7ab00> index path: (<NSIndexPath: 0x17d8fb30> length = 2, path = 0 - 0); element kind: (UICollectionElementKindSectionHeader); frame = (8 0; 314 50); zIndex = 10;  to <UICollectionViewLayoutAttributes: 0x17e9d770> index path: (<NSIndexPath: 0x17e96f70> length = 2, path = 0 - 0); element kind: (UICollectionElementKindSectionHeader); frame = (0 0; 314 50); zIndex = 10;  without invalidating the layout'

【问题讨论】:

【参考方案1】:

更新前需要使现有布局失效,见报错文末:

不使布局无效

你应该重写 UICollectionViewFlowLayout 子类的方法:

override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool 
        return true
    

更多参考请见Apple Documentation for UICollectionViewLayout

【讨论】:

以上是关于UICollectionView 自定义流布局在滚动时崩溃的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionView:如果为空部分,则自定义 FlowLayout 崩溃

iOS开发进阶 - 自定义UICollectionViewLayout实现瀑布流布局

UICollectionView:使用动画和自定义布局调整单元格大小

如何 UICollectionView 每列具有不同的行

更改 UICollectionView 的流布局

你如何设置UICollectionView动画时间?