UICollectionViewCompositionalLayout interface to implement complex collection view layout.


To run the example project, clone the repo, and run pod install from the Example directory first.


iOS 13.0+


CompositionalLayoutViewController is available through CocoaPods. To install
it, simply add the following line to your Podfile:

pod 'CompositionalLayoutViewController'


There are four steps to declare collection view.

Firstly, to compose complex collection view sections, you implement Section class that inherits HashableObject and CollectionViewSection.

class TextFormSection: HashableObject, CollectionViewSection {

Secondly, implement your sections layout.

func layoutSection(environment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection

Thirdly, register cells and supplementary views for collection view in func registerCell(collectionView: UICollectionView) and func registerSupplementaryView(collectionView: UICollectionView).

func registerCell(collectionView: UICollectionView) {
    // register cells here
func registerSupplementaryView(collectionView: UICollectionView) {
    // register supplementary views here

Make sure that you implement func supplementaryView(_ collectionView: UICollectionView, kind: String, indexPath: IndexPath) -> UICollectionReusableView?.
You may have to deque UICollectionReusableView from a collection view.

These cells and supplementary views are configured following methods.

func configuredCell(_ collectionView: UICollectionView, indexPath: IndexPath) -> UICollectionViewCell
func configureSupplementaryView(_ view: UICollectionReusableView, indexPath: IndexPath)

You also have to declare var snapshotItems: [AnyHashable] in your section class.
This variable contains datas for each cells.

var snapshotItems: [AnyHashable] {
    // return AnyHashable items

Finally, you can declare collection view sections in subclass of CompositionalLayoutViewController as follows:

sections = [
        items: [
                initialText: nil,
                textForm: .init(
                    placeholder: "Email",
                    validationHandler: { text in
                        guard let text = text else {
                            return false
                        return text.isValidEmailAddress()
                    validationAppearance: .init(
                        textColor: .red
                initialText: nil,
                textForm: .init(
                    placeholder: "Password",
                    isSecureTextEntry: true
        buttonTitle: "Login",
        action: .handler({
            print("Login button pressed")

And also don't forget to assign SectionProvider that manages an array of sections.

public protocol SectionProvider: AnyObject {
    var sections: [CollectionViewSection] { get }
    func section(for sectionIndex: Int) -> CollectionViewSection
override func viewDidLoad() {
    provider = // assign your provider e.g. presenter in VIPER

To handle cell selection, override func didSelectItem(at indexPath: IndexPath) method in subclass of CompositionalLayoutViewController.

See example code to lean advanced usage.


Akira, [email protected]