CollectionKit Documentation

repository·master·Indexed 26 days ago

https://github.com/soysaucelab/collectionkit

A modern Swift framework that reimagines UICollectionView by building it on top of UIScrollView. It offers a composable, data-driven approach to building collections featuring automatic diffing, built-in layouts like FlowLayout and WaterfallLayout, and a flexible animation system. The framework utilizes providers such as BasicProvider and ComposedProvider to manage data sources, view sources, and size sources.

Tokens
2.8K
Snippets
8
Records
13
Agent score
39%

What's inside CollectionKit

  1. Migrate ComposedProvider (formerly CollectionComposer)

    master

    The convenience initializer for CollectionComposer has been removed. When creating a ComposedProvider, pass your providers as an array to the sections parameter.

    // Old v1.3 pattern
    CollectionComposer(provider1, provider2, provider3)
    
    // New v2.0 pattern
    ComposedProvider(sections: [provider1, provider2, provider3])
    ComposedProvider(sections: [provider1, provider2, provider3])
  2. Reload data in CollectionView

    master

    CollectionKit automatically diffs data changes. Updating the data property of an ArrayDataSource will trigger an update.

    Update Strategies

    • Automatic: Updating the array inside an ArrayDataSource (e.g., dataSource.data.append(10)) automatically calls setNeedsReload().
    • Next Layout Cycle: Use collectionView.setNeedsReload(), provider.setNeedsReload(), or dataSource.setNeedsReload() to schedule an update for the next layout cycle. This is efficient as it batches multiple updates.
    • Immediate: Use collectionView.reloadData(), provider.reloadData(), or dataSource.reloadData() to trigger an immediate update.

    Warning: If you assign an array to a data source and then mutate the original local array variable, the CollectionView will not update because the data source holds its own copy.

  3. Migrate BasicProvider (formerly CollectionProvider) initialization

    master

    In v2.0, BasicProvider has changed its designated initializer and internal variable names.

    Variable name changes:

    • dataProvider $\rightarrow$ dataSource
    • viewProvider $\rightarrow$ viewSource
    • sizeProvider $\rightarrow$ sizeSource
    • presenter $\rightarrow$ animator

    Removed handlers:

    • willReloadHandler and didReloadHandler have been removed.

    New Initializer Pattern: Instead of using convenience initializers with direct data and closures, you must now explicitly provide a DataSource and a ViewSource.

    // Old v1.3 pattern
    CollectionProvider(
      data: data,
      viewUpdater: { (label: UILabel, data: Data, index: Int) in
        label.text = "\(data)"
      },
      sizeProvider: { (index: Int, data: Data, collectionSize: CGSize) -> CGSize in
        return CGSize(width: 50, height: 50)
      }
    )
    
    // New v2.0 pattern
    BasicProvider(
      dataSource: ArrayDataSource(data: data),
      viewSource: ClosureViewSource(viewUpdater: { (label: UILabel, data: Data, index: Int) in
        label.text = "\(data)"
      }),
      sizeSource: { (index: Int, data: Data, collectionSize: CGSize) -> CGSize in
        return CGSize(width: 50, height: 50)
      }
    )
    BasicProvider(
      dataSource: ArrayDataSource(data: data),
      viewSource: ClosureViewSource(viewUpdater: { (label: UILabel, data: Data, index: Int) in
        label.backgroundColor = .red
        label.layer.cornerRadius = 8
        label.textAlignment = .center
        label.text = "\(data)"
      }),
      sizeSource: { (index: Int, data: Data, collectionSize: CGSize) -> CGSize in
        return CGSize(width: 50, height: 50)
      }
    )
  4. Migrate class names from v1.3 to v2.0

    master

    CollectionKit v2.0 includes typealias bridges for deprecated names to prevent compilation errors, but you should update your code to the new naming convention for clarity. The following renames apply:

    v1.3 Namev2.0 Name
    CollectionProviderBasicProvider
    CollectionComposerComposedProvider
    ViewCollectionProviderSimpleViewProvider
    CollectionPresenterAnimator
    CollectionLayoutLayout
    AnyCollectionProviderProvider
    CollectionDataProviderDataSource
    CollectionViewProviderViewSource
    CollectionSizeProviderSizeSource
    EmptyStateCollectionProviderEmptyStateProvider
    SpaceCollectionProviderSpaceProvider
    ClosureDataProviderClosureDataSource
    ClosureViewProviderClosureViewSource
    ArrayDataProviderArrayDataSource
  5. Get started with CollectionView and BasicProvider

    master

    Replace UICollectionView with CollectionView. To display content, assign a Provider to the collectionView.provider property. The simplest way to create a provider is using BasicProvider, which requires three components:

    1. DataSource: An object that supplies data (e.g., ArrayDataSource).
    2. ViewSource: An object that maps data to a view and updates it (e.g., ClosureViewSource).
    3. SizeSource: A function that returns the CGSize for each cell.

    Example implementation:

    let dataSource = ArrayDataSource(data: [1, 2, 3, 4])
    let viewSource = ClosureViewSource(viewUpdater: { (view: UILabel, data: Int, index: Int) in
      view.backgroundColor = .red
      view.text = "\(data)"
    })
    let sizeSource = { (index: Int, data: Int, collectionSize: CGSize) -> CGSize in
      return CGSize(width: 50, height: 50)
    }
    let provider = BasicProvider(
      dataSource: dataSource,
      viewSource: viewSource,
      sizeSource: sizeSource
    )
    
    // Assign the provider to the collectionView to display content
    collectionView.provider = provider
  6. Migrate SimpleViewProvider (formerly ViewCollectionProvider)

    master

    The convenience initializer for ViewCollectionProvider has been removed. Use the views array parameter in SimpleViewProvider instead.

    // Old v1.3 pattern
    ViewCollectionProvider(view1, view2)
    
    // New v2.0 pattern
    SimpleViewProvider(views: [view1, view2])
    SimpleViewProvider(views: [view1, view2])
  7. Apply Animations to CollectionView, Providers, or Views

    master

    Assign an Animator to control how cells are displayed and how they animate during additions, moves, or deletions. Animators follow a priority hierarchy:

    1. View Level: view.collectionAnimator (Highest priority)
    2. Provider Level: provider.animator (Overrides CollectionView)
    3. CollectionView Level: collectionView.animator (Lowest priority)

    Note: To use WobbleAnimator, you must include the CollectionKit/WobbleAnimator subspec in your Podfile.

  8. Migrate Animator (formerly CollectionPresenter)

    master

    The base Animator class no longer handles animations directly. The following methods have been removed from the base class:

    • insertAnimation
    • deleteAnimation
    • updateAnimation

    New Animators available in v2.0:

    • ScaleAnimator
    • FadeAnimator

    Note: ZoomAnimator has been moved to the CollectionKitExample project.

  9. Migrate TapHandler to TapContext

    master

    The TapHandler signature has changed from a simple closure to a closure that accepts a TapContext object. This provides access to the view, index, data source, and the data itself.

    Old Signature: typealias TapHandler = (View, Int, DataSource<Data>) -> Void

    New Signature: typealias TapHandler = (TapContext) -> Void

    TapContext Protocol:

    protocol TapContext {
      var view: View { get }
      var index: Int { get }
      var dataSource: DataSource<Data> { get }
      var data: Data { get }
      func setNeedsReload() {}
    }
  10. Implement custom Layout using LayoutContext

    master

    In v2.0, Layout is data-independent and no longer receives the dataProvider or sizeProvider directly. Instead, the layout(context:) method provides a LayoutContext object to retrieve necessary information.

    LayoutContext Protocol:

    public protocol LayoutContext {
      var collectionSize: CGSize { get }
      var numberOfItems: Int { get }
      func data(at: Int) -> Any
      func identifier(at: Int) -> String
      func size(at: Int, collectionSize: CGSize) -> CGSize
    }

    Implementation Example:

    func layout(context: LayoutContext) {
      // Use context.collectionSize, context.numberOfItems, 
      // context.data(at:), and context.size(at:collectionSize:) 
      // to perform layout logic.
    }
    public protocol LayoutContext {
      var collectionSize: CGSize { get }
      var numberOfItems: Int { get }
      func data(at: Int) -> Any
      func identifier(at: Int) -> String
      func size(at: Int, collectionSize: CGSize) -> CGSize
    }
    
    func layout(context: LayoutContext) {}
  11. Configure Layouts

    master

    Assign a Layout object to the provider.layout property to control item positioning and spacing.

    Built-in Layouts

    • FlowLayout: A better UICollectionViewFlowLayout supporting lineSpacing, interitemSpacing, alignContent, alignItems, and justifyContent.
    • WaterfallLayout
    • RowLayout

    Layout Transformations

    • inset(by:): Adds outer padding to a layout. Returns an InsetLayout.
    • transposed(): Converts a vertical layout to horizontal or vice-versa. Returns a TransposedLayout.

    Example of combining transformations:

    let inset = UIEdgeInset(top: 10, left: 10, bottom: 10, right: 10)
    provider.layout = FlowLayout(spacing: 10).transposed().inset(by: inset)