Skip to content
Snippets Groups Projects
CellFactory.swift 1.8 KiB
Newer Older
Dariusz Rybicki's avatar
Dariusz Rybicki committed
import UIKit
import XCTestDynamicOverlay
Dariusz Rybicki's avatar
Dariusz Rybicki committed

public struct CellFactory<Model> {
  public struct Registrar {
Dariusz Rybicki's avatar
Dariusz Rybicki committed
    public init(register: @escaping (UICollectionView) -> Void) {
      self.register = register
    }

Dariusz Rybicki's avatar
Dariusz Rybicki committed
    public var register: (UICollectionView) -> Void

    public func callAsFunction(in view: UICollectionView) {
      register(view)
    }
  }

  public struct Builder {
Dariusz Rybicki's avatar
Dariusz Rybicki committed
    public init(build: @escaping (Model, UICollectionView, IndexPath) -> UICollectionViewCell?) {
      self.build = build
    }

    public var build: (Model, UICollectionView, IndexPath) -> UICollectionViewCell?
Dariusz Rybicki's avatar
Dariusz Rybicki committed

    public func callAsFunction(
      for model: Model,
      in view: UICollectionView,
      at indexPath: IndexPath
    ) -> UICollectionViewCell? {
Dariusz Rybicki's avatar
Dariusz Rybicki committed
      build(model, view, indexPath)
Dariusz Rybicki's avatar
Dariusz Rybicki committed
    }
  }

  public init(
    register: Registrar,
    build: Builder
  ) {
    self.register = register
    self.build = build
  }
Dariusz Rybicki's avatar
Dariusz Rybicki committed

  public var register: Registrar
  public var build: Builder
Dariusz Rybicki's avatar
Dariusz Rybicki committed
}

extension CellFactory {
  public static func combined(_ factories: CellFactory...) -> CellFactory {
    combined(factories)
  }

  public static func combined(_ factories: [CellFactory]) -> CellFactory {
    CellFactory(
      register: .init { collectionView in
        factories.forEach { $0.register(in: collectionView) }
      },
      build: .init { model, collectionView, indexPath in
        for factory in factories {
          if let cell = factory.build(for: model, in: collectionView, at: indexPath) {
            return cell
          }
        }
        return nil
Dariusz Rybicki's avatar
Dariusz Rybicki committed
      }
    )
  }
}

#if DEBUG
extension CellFactory {
  public static func unimplemented() -> CellFactory {
Dariusz Rybicki's avatar
Dariusz Rybicki committed
    CellFactory(
      register: .init(register: XCTUnimplemented("\(Self.self).Registrar")),
      build: .init(build: XCTUnimplemented("\(Self.self).Builder"))
Dariusz Rybicki's avatar
Dariusz Rybicki committed
    )
  }
}
#endif