CollectionModel 0.4.0

CollectionModel 0.4.0

Denis Poifol 维护。



CollectionModel

CI Version License Platform

此 pod 的目标是提供一个数据结构来表示 collectionView/tableView 所显示的内容。它使您能够将任何业务逻辑从视图的 dataSource 中提取到负责生成其 viewModel 的代码部分。这有助于在应用程序中强制更好的关注点分离,并保持 dataSource 易于维护。

示例应用程序

要运行示例项目,请克隆仓库,然后从 Example 目录首先运行 bundle install & bundle exec pod install

使用方法

一切在 Xcode 中都有文档。

TableViewModel

TableViewModel 是一个结构体,尽可能地代表 UITableView 的结构。它是两个参数的泛型:HeaderFooterViewModelCellViewModel,这两个参数都很直观,它们应该代表用于配置 tableView 单元格或头部和尾部模型所使用的模型。

这个结构体主要是一个数组的包装器,该数组代表了 TableViewSectionViewModel 的数组,而 TableViewSectionViewModel 是一个结构体,代表 UITableView 的一个部分。

TableViewSectionViewModel依赖于cellViewModels数组以及两个可空的标题和页脚属性。

如果您只使用一种类型的单元格,则基于tableViewModel实现tableViewDataSource相对简单。

class SimpleTableViewDataSource: NSObject,
    UITableViewDataSource {

    typealias ViewModel = TableViewModel<Never, ATableViewCellModel>

    var viewModel = ViewModel()

    func numberOfSections(in tableView: UITableView) -> Int {
        viewModel.sections.count
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        viewModel[section].cells.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: ATableViewCell = tableView.dequeueCell(at: indexPath)
        cell.configure(with: viewModel[indexPath])
        return cell
    }
}

如果必须使用多种类型的单元格,您应该为细胞类型创建一个枚举。

enum MultipleCellTypesTableViewCellModel {
    case a(ATableViewCellModel)
    case b(BTableViewCellModel)
}

这将只需要更改您对tableView(_:cellForRowAt:)的实现,以管理细胞类型的情况。

有关更多详细信息,请参阅示例应用程序。

CollectionViewModel

CollectionViewModel是一个结构体,它尽可能准确地表示UICollectionView的结构。它是关于两个参数的泛型SupplementaryViewModelCellViewModel,这两个参数都应该是自解释的,它们应该代表用于配置collectionView单元格或可能是标题、页脚或自定义补充视图的补充视图所使用的模型。

这个结构体主要是对CollectionSectionViewModel数组的包装,这是一个结构体,代表UICollectionView的一节。

CollectionSectionViewModel依赖于一个cellViewModels数组以及一个存储着补充ViewModels的字典,其中键是SupplementaryViewSectionKey,是一个索引和补充视图类型的配对。该节的标题和页脚存储在自己的变量中,独立于字典。

如果您只使用一种类型的单元格,基于CollectionViewModel实现collectionViewDataSource相对简单。

class SimpleCollectionViewDataSource: NSObject,
    UICollectionViewDataSource {
	
	typealias ViewModel = CollectionViewModel<Never, CollectionViewCellModel>

    var viewModel = ViewModel()

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        viewModel.sections.count
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        viewModel[section].cells.count
    }

    func collectionView(_ collectionView: UICollectionView,
                        cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell: ACollectionViewCell = collectionView.dequeueCell(at: indexPath)
        cell.configure(with: viewModel.cellViewModel(at: indexPath))
        return cell
    }
}

如果必须使用多种类型的单元格,您应该为细胞类型创建一个枚举。

enum MultipleCellTypesCollectionViewCellModel {
    case a(ACollectionViewCellModel)
    case b(BCollectionViewCellModel)
}

这将只需要更改您对collectionView(_:cellForItemAt:)的实现,以管理单元格类型的情况。

函数构建器

从CollectionModelCore 0.1.1(CollectionModel 0.2.1)起,您可以使用函数构建器提供的声明性语法创建viewModel。您可以使用两种不同的函数构建器来创建ViewModel或部分。

简单的声明式

您可以用声明式的方法创建一个部分或viewModel

Section {
    cell1
    if condition {
        [
            cell2,
            cell3,
        ]
    } else {
        cell4
    }
}

此实现支持if/else语句,这意味着它也支持switch。如示例所示,您可以从每一行返回一个单元格或单元格集合。但是,请注意,它支持任何单元格集合,因此请注意无序集合。

基于实体

由于当前无法在函数构建器中支持循环,因此提供了一个基于实体数组迭代的函数构建器。大多数情况下,您的实现将如下所示

Section(entities: entities) { entity in
    cell1(for: entity)
}

但有时候您可能希望为单个实体返回多个单元,这也是可能的。

Section(entities: entities) { entity in
    cell1(for: entity)
    if condition {
        [
            cell2(for: entity),
            cell3(for: entity),
        ]
    } else {
        cell(for: entity)
    }
}

如您所见,此实现还支持if/else语句并返回集合而不是单个元素。

需求

除了使用 Swift 之外,没有使用此 pod 的技术要求。

安装

CollectionModel 通过 CocoaPods 提供。要安装它,只需将以下行添加到您的 Podfile

pod 'CollectionModel'

作者

Denis Poifol[email protected]

许可

CollectionModel 在 MIT 许可下可用。有关更多信息,请参阅 LICENSE 文件。