Q:

Connecting Custom layout class to collection view in code

i have a small question about a custom layout class and i need to connect it to my collection view in code not by the story board because i create the whole project by code . any help, please ? 
my main class 
import UIKit
import Firebase
class UserProfileController: UICollectionViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView?.backgroundColor = .white
        //fetchUser()
        collectionView?.dataSource = self
        collectionView?.delegate = self
        collectionView?.register(TestCell.self, forCellWithReuseIdentifier: mainCellId)    
    }

    fileprivate let mainCellId = "mainCellId"
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: mainCellId, for: indexPath) as! TestCell

        return cell
    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 15
    }
    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
}

the custom layout class which need to connect it to the collection view in code not story board 
import UIKit

struct UltraVisualLayoutConstants {
    struct Cell {
        static let standardHeight: CGFloat = 100
        static let featuredHeight: CGFloat = 280
//        static let standardWidth: CGFloat = 100
//        static let featuredWidth: CGFloat = 280
    }
}

class UltraVisualLayout: UICollectionViewLayout {
    //  amount which users need to scroll before featured cell changes\
    let dragOffset: CGFloat = 180.0
    var cache = [UICollectionViewLayoutAttributes]()
    //return item index of current featured cell
    var featuredItemIndex: Int {
        get {
            //use max to ensure that featureditemindex never be < 0
            return max(0 , Int(collectionView!.contentOffset.y / dragOffset))
        }
    }

    // returns value between 0 and 1 to represent how close the next cell becomes the featured cell
    var nextItemPercentegeOffset: CGFloat {
        get {
            return (collectionView!.contentOffset.y / dragOffset) - CGFloat(featuredItemIndex)
        }
    }    
    // return the width of collection view
    var width: CGFloat {
        get {

            guard let width = collectionView?.bounds.width else {return 0}
            return width
        }
    }
    // return the height of collection view
    var height: CGFloat {
        get {
            guard let height = collectionView?.bounds.height else {return 0}
            return height
        }
    }
    //returns the number of items in the collection view
    var numberOfItems: Int {
        get {
            return collectionView!.numberOfItems(inSection: 0)
        }
    }

    // MARK: UICollectionViewLayout
    // return the size of all content in collection view
     override var collectionViewContentSize: CGSize {
   let contentHeight = (CGFloat(numberOfItems) * dragOffset) + (height - dragOffset)
    return CGSize(width: width, height: contentHeight)
}
    override func prepare() {
        cache.removeAll(keepingCapacity: false)

        let standardHeight = UltraVisualLayoutConstants.Cell.standardHeight
        let featuredHeight = UltraVisualLayoutConstants.Cell.featuredHeight
        var frame = CGRect(x: 0, y: 0, width: 0, height: 0)
        var y: CGFloat = 0
        for item in 0..<numberOfItems {
            let indexPath = NSIndexPath(item: item, section: 0)
            let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath as IndexPath)
            attributes.zIndex = item
            var height = standardHeight
            if indexPath.item == featuredItemIndex {
                let yOffset = standardHeight * nextItemPercentegeOffset
                y = collectionView!.contentOffset.y - yOffset
                height = featuredHeight
            } else if indexPath.item == (featuredItemIndex + 1) && indexPath.item != numberOfItems {
                let maxY = y + standardHeight
                height = standardHeight + max((featuredHeight - standardHeight) * nextItemPercentegeOffset, 0)
                y = maxY - height
            }
         frame = CGRect(x: 0, y: y, width: width, height: height)
            attributes.frame = frame
            cache.append(attributes)
            y = frame.maxY
        }

    }

    // return all attributes in cache whose frame intersects with the rect passed to the method
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        var layoutAttributes = [UICollectionViewLayoutAttributes]()
        for attributes in cache {
            if attributes.frame.intersects(rect) {
                layoutAttributes.append(attributes)
            }
        }
        return layoutAttributes
    }

    // return true so that layout is continuously invalidated as the user scrolls
    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        return true 
    }

A:

You cannot set the layout programmatically if you don't have an initializer. From the docs:

layout
The layout object to use for organizing items. The collection
view stores a strong reference to the specified object. Must not be
nil.

Since you seem to be using the storyboard, you'll have to set it there.

Once you create you layout class in code, it will show up when you click you collection view on the storyboard. The default layout will be set to Flow, when you change it to Custom, a new class field will show up. When you click that, it will list your layout class. You can choose it and set it from there.
However if you are initializing your storyboard programmatically, then you just need to pass it as a parameter to your initializer.
var collectionView = UICollectionView(frame: yourFrame, collectionViewLayout: customCollectionViewLayout)    // pass your custom collection view instance

