ReactiveCollectionsKit CI

Data-driven, declarative, reactive, diffable collections (and lists!) for iOS. A thoughtful and flexible wrapper for UICollectionView done right.

Project Status: WIP ⚠️

⚠️ This is still a Work-In-Progress, but it is close to finished. I started this a few years back, then got busy with other things. I am now returning to the project to get the initial release complete. Hopefully. 🤞

In any case, what’s here now is worth sharing.

About

This library is the culmination of everything I learned from building and maintaining IGListKit, ReactiveLists, and JSQDataSourcesKit. The 4th time’s a charm! 🍀

Improvements over the libraries above include:

  • All Swift and zero third-party dependencies
  • Generic view models to represent and configure cells
  • Mix multiple data types
  • Automatic registration for cells and supplementary views
  • Automatic diffing for items and sections
  • Simply UICollectionView and UICollectionViewCompositionalLayout at its core.
  • No UITableView. UICollectionView now has a List Layout.

What about SwiftUI?

SwiftUI performance is still a significant issue, not to mention all the bugs and missing APIs. SwiftUI still does not provide a proper UICollectionView replacement. (Yes, Grid exists but it is nowhere close to a replacement for UICollectionView and UICollectionViewLayout.) While SwiftUI’s List is pretty good, both LazyVStack and LazyHStack suffer from severe performance issues when you have large amounts of data.

Main Features

TODO

⚠️ Work-In-Progress ⚠️

Usage

[!TIP]

Check out the extensive example project included in this repo.

Here’s an example of buliding a simple, static list from an array of data models.

class MyViewController: UICollectionViewController, CellEventCoordinator {

    var driver: CollectionViewDriver!

    override func viewDidLoad() {
        super.viewDidLoad()

        let models = [/* array of some data models */]

        // create cell view models from the data models
        let cellViewModels = models.map {
            MyCellViewModel($0)
        }

        // create your sections, and add cells
        let section = SectionViewModel(id: "my_section", cells: cellViewModels)

        // create the collection with all the sections
        let collectionViewModel = CollectionViewModel(sections: [section])

        // create your collection view layout
        let layout = UICollectionViewCompositionalLayout.list(
            using: .init(appearance: .insetGrouped)
        )

        // initialize the driver will all of the above
        self.driver = CollectionViewDriver(
            view: self.collectionView,
            layout: layout,
            viewModel: collectionViewModel,
            cellEventCoordinator: self
        )

        // the collection is updated and animated automatically

        // later, you can update the model like so:
        let updatedCollectionViewModel = CollectionViewModel(sections: [/* updated items and sections */])
        self.driver.viewModel = updatedCollectionViewModel
    }

    // MARK: CellEventCoordinator

    func didSelectCell(viewModel: any CellViewModel) {
        // TODO: handle cell selection events
    }
}

Requirements

Installation

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/jessesquires/ReactiveCollectionsKit.git", from: "0.1.0")
]

Alternatively, you can add the package directly via Xcode.

Documentation

You can read the documentation here. Generated with jazzy. Hosted by GitHub Pages.

Additional Resources

Contributing

Interested in making contributions to this project? Please review the guides below.

Also, consider sponsoring this project or buying my apps! ✌️

Credits

Created and maintained by Jesse Squires.

License

Released under the MIT License. See LICENSE for details.

Copyright © 2019-present Jesse Squires.