CompositionalLayoutViewController

UICollectionViewCompositionalLayout interface to implement complex collection view layout.

Example

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

Requirements

iOS 13.0+

Installation

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

pod 'CompositionalLayoutViewController'

Usage

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 = [
    TextFormSection(
        items: [
            .init(
                initialText: nil,
                textForm: .init(
                    placeholder: "Email",
                    validationHandler: { text in
                        guard let text = text else {
                            return false
                        }
                        return text.isValidEmailAddress()
                    },
                    validationAppearance: .init(
                        textColor: .red
                    )
                )
            ),
            .init(
                initialText: nil,
                textForm: .init(
                    placeholder: "Password",
                    isSecureTextEntry: true
                )
            )
        ]
    ),
    ButtonSection(
        buttonTitle: "Login",
        action: .handler({
            print("Login button pressed")
        })
    )
]
reloadSections()

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() {
    super.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.

Author

Akira, [email protected]

GitHub

https://github.com/oneinc-jp/CompositionalLayoutViewController