UICollectionView中具有自定义UICollectionViewLayout的节的标题

时间:2014-10-21 11:15:20

标签: ios swift uicollectionview uicollectionviewlayout

我正在使用自定义布局处理UICollectionView。在两天内,我无法理解如何向UICollectionView添加标头。我有非常简单的视图控制器(在自定义布局的故事板中创建):

class ACollectionViewController: UICollectionViewController {

    enum Identifiers: String {
        case CellIdentifier = "Cell"
        case HeaderIdentifier = "Header"
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.collectionView.registerClass(UICollectionReusableView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: Identifiers.HeaderIdentifier.rawValue)
    }

    // MARK: UICollectionViewDataSource
    override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 1
    }

    override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }

    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(Identifiers.CellIdentifier.rawValue, forIndexPath: indexPath) as Cell
        cell.backgroundColor = UIColor.redColor()
        return cell
    }

    override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
        println("ip = \(indexPath.item)")
        var supplementaryView = collectionView.dequeueReusableCellWithReuseIdentifier(Identifiers.HeaderIdentifier.rawValue, forIndexPath: indexPath) as UICollectionReusableView
        supplementaryView.backgroundColor = UIColor.blueColor()
        return supplementaryView
    }

这是我的自定义布局:

class ALayout: UICollectionViewLayout {

    override func prepareLayout() {
        super.prepareLayout()
    }

    override func collectionViewContentSize() -> CGSize {
        return self.collectionView!.bounds.size
    }

    let itemWidth = 40
    override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes! {
        var attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)

        let x: Float = Float(10) * Float(indexPath.item)
        let y: Float = Float(indexPath.item * itemWidth)
        attributes.frame = CGRect(x: CGFloat(x), y: CGFloat(y), width: CGFloat(itemWidth), height: CGFloat(itemWidth))

        return attributes
    }

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? {
        var attributes = [UICollectionViewLayoutAttributes]()

        let sectionsCount = self.collectionView!.dataSource!.numberOfSectionsInCollectionView!(self.collectionView!)
        for section in 0..<sectionsCount {
            /// add header
            attributes.append(self.layoutAttributesForSupplementaryViewOfKind(UICollectionElementKindSectionHeader, atIndexPath: NSIndexPath(forItem: 0, inSection: section)))

            let itemsCount = self.collectionView!.numberOfItemsInSection(section)
            for item in 0..<itemsCount {
                let indexPath = NSIndexPath(forItem: item, inSection: section)
                attributes.append(self.layoutAttributesForItemAtIndexPath(indexPath))
            }
        }

        return attributes
    }

    override func layoutAttributesForSupplementaryViewOfKind(elementKind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes! {
        var attributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: elementKind, withIndexPath: indexPath)
        attributes.frame = CGRect(x: 0, y: 0, width: 320, height: 50)

        return attributes
    }
}

问题是我不明白如何正确添加节标题,这个标题的indexPath应该是什么。代码中有注释添加了标题。应用程序在启动时崩溃

2014-10-21 13:06:22.793 UICollectionViewLayout-Demo[3805:95924] *** Terminating app due to 
uncaught exception 'NSInternalInconsistencyException', reason: 'could not dequeue a view of 
kind: UICollectionElementKindCell with identifier Header - must register a nib or a class for 
the identifier or connect a prototype cell in a storyboard'

我理解,这是因为cell与我尝试添加的节标题具有相同的indexPath,但是标题的indexPath应该是什么?或者我可能完全错了?

提前谢谢。

3 个答案:

答案 0 :(得分:9)

因为您正在使用

而导致崩溃
var supplementaryView = collectionView.dequeueReusableCellWithReuseIdentifier(Identifiers.HeaderIdentifier.rawValue, forIndexPath: indexPath) as UICollectionReusableView

尝试将页眉和页脚出列(在collectionView:viewForSupplementaryElementOfKind中)。将其更改为

var supplementaryView = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier:Identifiers.HeaderIdentifier.rawValue, forIndexPath: indexPath) as UICollectionReusableView

应该摆脱崩溃,因此您可以调查indexPath。但在我的测试中,indexPath始终只是&#34; 0&#34;。

答案 1 :(得分:1)

而不是var supplementaryView = collectionView.dequeueReusableCellWithReuseIdentifier(Identifiers.HeaderIdentifier.rawValue, forIndexPath: indexPath) as UICollectionReusableView

应该是

let supplementaryView = collectionView.dequeueReusableSupplementaryViewOfKind(kind withReuseIdentifier:Identifiers.HeaderIdentifier.rawValue, forIndexPath:indexPath)

答案 2 :(得分:1)

您使用错误的标题功能。根据Apple文档,使用以下内容作为页眉和页脚:

func dequeueReusableSupplementaryViewOfKind(_ elementKind: String,
                        withReuseIdentifier identifier: String,
                               forIndexPath indexPath: NSIndexPath!) -> AnyObject

代替:

 var supplementaryView = collectionView.dequeueReusableCellWithReuseIdentifier(Identifiers.HeaderIdentifier.rawValue, forIndexPath: indexPath) as UICollectionReusableView