Giter Club home page Giter Club logo

reactivecollectionskit's Introduction

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

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.

reactivecollectionskit's People

Contributors

anayini avatar dependabot[bot] avatar jessesquires avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

reactivecollectionskit's Issues

Drop TableView Support

CollectionView has advanced sufficiently with UICollectionLayoutListConfiguration, etc. such that TableView simply isn't worth supporting — much less trying to "unify" the APIs between collections and tables.

The List APIs for CollectionView are iOS 14+, but with iOS 15 on the horizon, it's not really worth any of this effort at this point to support iOS 13 or table view. (At least, I certainly won't be deploying to iOS 13.)

If users want good table view support with a similar API, they should use ReactiveLists.

See:

Legacy branch created in case we need/want to reference this:
https://github.com/jessesquires/ReactiveCollectionsKit/tree/legacy-table-view-support

Handle self-sizing cells/headers/footers and estimated size methods?

We need to be able to handle self-sizing cells/headers/footers, instead of only explicit sizes.

Apparently, self-sizing cells is only a thing for table view — not collection view.
(I thought both had this feature, but I guess not.)

Currently, clients have to do this:

/// in CellViewModel implementation
func size<V: UIView & CellContainerViewProtocol>(in containerView: V) -> CGSize {
    return CGSize(width: 0, height: UITableView.automaticDimension)
}

Maybe we can find a way to simplify and reduce the duplication.

Update repo settings

Once open source:

  • test Danger (per #22)
  • update repo settings to make workflows required for PRs

Support for tvOS?

This should be much easier than macOS support, since tvOS just uses UIKit.

This should mostly be a matter of configuration.

A rough ToDo list:

  • Configure the project to run on tvOS
  • Add any necessary #if os() checks
  • Add a test target for tvOS to run existing tests on tvOS
  • Update CI config to run new tests
  • Update Package.swift and podspec

Support for macOS?

⚠️ This is a very large task. Please coordinate here before doing any work.

ℹ️ I don't have a need for this yet, but might in the future.

ToDo

Here's a rough, high-level outline of what needs to be done.

  • Figure out the main differences between the NSCollectionView infra and UICollectionView infra
  • What can we reuse? What cannot be reused?
  • Should macOS just get its own library? Does it make sense to include it here?
  • Tests for everything
  • Add macOS example app to demonstrate, write UI Tests

Resources

Implement additional context menu APIs

Docs: https://developer.apple.com/documentation/uikit/uicollectionviewdelegate

Already implemented

func collectionView(UICollectionView, contextMenuConfigurationForItemAt: IndexPath, point: CGPoint) -> UIContextMenuConfiguration?

NOT implemented

func collectionView(UICollectionView, previewForDismissingContextMenuWithConfiguration: UIContextMenuConfiguration) -> UITargetedPreview?
func collectionView(UICollectionView, previewForHighlightingContextMenuWithConfiguration: UIContextMenuConfiguration) -> UITargetedPreview?

func collectionView(UICollectionView,  willDisplayContextMenu configuration: UIContextMenuConfiguration,  animator: UIContextMenuInteractionAnimating?)
func collectionView(UICollectionView, willEndContextMenuInteraction configuration: UIContextMenuConfiguration,  animator: UIContextMenuInteractionAnimating?)

func collectionView(UICollectionView, willPerformPreviewActionForMenuWith: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating)

Implement empty states

Would be nice to provide an "empty state view" API.

ContainerViewModel.emptyStateView

init ContainerViewModel with a closure () -> UIView that constructs the empty state view.

This way, we can create it on-the-fly, only when it's needed.

Finish CI setup

Keep using GitHub actions or switch to TravisCI?

Not sure if GH Actions can do everything we need. Maybe use both?

ToDo:

Notes:

GH now using macOS 10.15:
https://help.github.com/en/actions/automating-your-workflow-with-github-actions/software-installed-on-github-hosted-runners#macos-1015

Example:
https://github.com/plangrid/ReactiveLists/blob/master/.github/workflows/ci.yml

[DataSource] implement section index titles

CollectionView docs

optional func indexTitles(for collectionView: UICollectionView) -> [String]?

optional func collectionView(_ collectionView: UICollectionView,  indexPathForIndexTitle title: String, at index: Int) -> IndexPath

This will need to be implemented at the CollectionViewModel level.

Maybe we wrap this functionality in a new protocol, pass that in, then call these methods via the data source implementation.

Rough example:

protocol IndexTitleViewModel {

    var indexTitles: [String]? { get }
    
    func indexPathForIndexTitle(_ title: String, at index: Int) -> IndexPath
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.