Adding a HeaderView to CollectionView when using custom FlowLayout (Swift)
<p>I've implemented a custom <code>FlowLayout</code> subclass, which apparently has precluded me from adding a <code>headerView</code> via the <code>storyboard</code> (the check box is gone).  Is there any other way to do so using <code>storyboards</code>? </p>

<p>There are some answers about how to add a <code>headerView</code> programmatically but they're in <code>objective-C</code>, how can I add one using <code>Swift</code>? </p>

<p>The below doesn't produce a header view and I can't figure out why? </p>

<pre><code> CollectionViewController {


    override func viewDidLoad() {
        super.viewDidLoad()

            // Setup Header
        self.collectionView!.registerClass(PinHeaderView.self, forSupplementaryViewOfKind:UICollectionElementKindSectionHeader, withReuseIdentifier: headerIdentifier)

}
     override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -&gt; UICollectionReusableView {
                //1
                switch kind {
                    //2
                case UICollectionElementKindSectionHeader:
                    //3
                    let headerView = collectionView.dequeueReusableSupplementaryViewOfKind(kind,withReuseIdentifier: "PinHeaderView",
                        forIndexPath: indexPath)
                        as! PinHeaderView
                    headerView.pinHeaderLabel.text = boardName
                    return headerView
                default:
                    //4
                    fatalError("Unexpected element kind")
                }
        }
    }

class PinHeaderView: UICollectionReusableView {


    @IBOutlet weak var pinHeaderLabel: UILabel!



}
</code></pre>

<p>My Layout class: </p>

<pre><code>import UIKit
protocol PinterestLayoutDelegate {
    // 1. Method to ask the delegate for the height of the image
    func collectionView(collectionView:UICollectionView, heightForPhotoAtIndexPath indexPath:NSIndexPath , withWidth:CGFloat) -&gt; CGFloat
    // 2. Method to ask the delegate for the height of the annotation text
    func collectionView(collectionView: UICollectionView, heightForAnnotationAtIndexPath indexPath: NSIndexPath, withWidth width: CGFloat) -&gt; CGFloat

    func columnsForDevice() -&gt; Int

}

class PinterestLayoutAttributes:UICollectionViewLayoutAttributes {

    // 1. Custom attribute
    var photoHeight: CGFloat = 0.0
    var headerHeight: CGFloat = 0.0

    // 2. Override copyWithZone to conform to NSCopying protocol
    override func copyWithZone(zone: NSZone) -&gt; AnyObject {
        let copy = super.copyWithZone(zone) as! PinterestLayoutAttributes
        copy.photoHeight = photoHeight
        return copy
    }

    // 3. Override isEqual
    override func isEqual(object: AnyObject?) -&gt; Bool {
        if let attributtes = object as? PinterestLayoutAttributes {
            if( attributtes.photoHeight == photoHeight  ) {
                return super.isEqual(object)
            }
        }
        return false
    }
}


class PinterestLayout: UICollectionViewLayout {
    //1. Pinterest Layout Delegate
    var delegate:PinterestLayoutDelegate!

    //2. Configurable properties
    //moved numberOfColumns
    var cellPadding: CGFloat = 6.0

    //3. Array to keep a cache of attributes.
    private var cache = [PinterestLayoutAttributes]()

    //4. Content height and size
    private var contentHeight:CGFloat  = 0.0
    private var contentWidth: CGFloat {
        let insets = collectionView!.contentInset
        return CGRectGetWidth(collectionView!.bounds) - (insets.left + insets.right)
    }

    override class func layoutAttributesClass() -&gt; AnyClass {

        return PinterestLayoutAttributes.self


    }

    override func prepareLayout() {
        // 1. Only calculate once
        //if cache.isEmpty {

            // 2. Pre-Calculates the X Offset for every column and adds an array to increment the currently max Y Offset for each column
            let numberOfColumns = delegate.columnsForDevice()
            let columnWidth = contentWidth / CGFloat(numberOfColumns)
            var xOffset = [CGFloat]()
            for column in 0 ..&lt; numberOfColumns {
                xOffset.append(CGFloat(column) * columnWidth )
            }
            var column = 0
            var yOffset = [CGFloat](count: numberOfColumns, repeatedValue: 0)

            // 3. Iterates through the list of items in the first section
            for item in 0 ..&lt; collectionView!.numberOfItemsInSection(0) {

                let indexPath = NSIndexPath(forItem: item, inSection: 0)

                // 4. Asks the delegate for the height of the picture and the annotation and calculates the cell frame.
                let width = columnWidth - cellPadding*2
                let photoHeight = delegate.collectionView(collectionView!, heightForPhotoAtIndexPath: indexPath , withWidth:width)
                let annotationHeight = delegate.collectionView(collectionView!, heightForAnnotationAtIndexPath: indexPath, withWidth: width)
                let height = cellPadding +  photoHeight + annotationHeight + cellPadding
                let frame = CGRect(x: xOffset[column], y: yOffset[column], width: columnWidth, height: height)
                let insetFrame = CGRectInset(frame, cellPadding, cellPadding)

                // 5. Creates an UICollectionViewLayoutItem with the frame and add it to the cache
                let attributes = PinterestLayoutAttributes(forCellWithIndexPath: indexPath)
                attributes.photoHeight = photoHeight
                attributes.frame = insetFrame
                cache.append(attributes)

                // 6. Updates the collection view content height
                contentHeight = max(contentHeight, CGRectGetMaxY(frame))
                yOffset[column] = yOffset[column] + height

                column = column &gt;= (numberOfColumns - 1) ? 0 : ++column
            }
        //}
    }


    override func layoutAttributesForSupplementaryViewOfKind(elementKind: String, atIndexPath indexPath: NSIndexPath) -&gt; UICollectionViewLayoutAttributes? {

       let attributes = PinterestLayoutAttributes(forSupplementaryViewOfKind: elementKind, withIndexPath: indexPath)
    attributes.headerHeight = 100.0
    attributes.frame = (self.collectionView?.frame)!
    return attributes



    }


    override func collectionViewContentSize() -&gt; CGSize {
        return CGSize(width: contentWidth, height: contentHeight)
    }

    override func layoutAttributesForElementsInRect(rect: CGRect) -&gt; [UICollectionViewLayoutAttributes]? {

        var layoutAttributes = [UICollectionViewLayoutAttributes]()

        // Loop through the cache and look for items in the rect
        for attributes  in cache {
            if CGRectIntersectsRect(attributes.frame, rect ) {
                layoutAttributes.append(attributes)
            }
        }
        return layoutAttributes
    }
}
</code></pre>