DKDataSources 1.0.0

DKDataSources 1.0.0

Denis Kakačka 维护。



DKDataSources

Version License Platform

DKDataSource 是您解决在 TableViewsCollectionViews 中多重 cell 类型常见问题的整洁方案,也为在 cellForRowheightForRow 等中的 if indexPath.section == 0 等类似语句提供了优雅的解决方案。

这是第一张截图中的 ViewController 代码。

lazy var dataSource = DKTableDataSource<CellType>(
    models: [
        DisclosureCellModel(title: "Disclosure 1", action: .action1),
        TextFieldCellModel(title: "TextField 1", placeholder: "Placeholder 1"),
        SwitchCellModel(title: "Switch 1", isOn: true),
        BannerCellModel(imageName: "placeholder"),
        SwitchCellModel(title: "Switch 2", isOn: false),
        BannerCellModel(imageName: "placeholder"),
        DisclosureCellModel(title: "Disclosure 2", action: .action2),
        TextFieldCellModel(title: "TextField 2", placeholder: "Placeholder 2"),
        BannerCellModel(imageName: "placeholder")
    ]
)

// in `viewDidLoad`
dataSource.registerCells(for: tableView)
tableView.dataSource = dataSource

示例

要运行示例项目,请克隆仓库,并首先从 Example 目录运行 pod install

安装

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

pod 'DKDataSources'

用法

在您使用 DKDataSources 时,需要满足一些要求使其正常工作。首先,您需要一个符合 DKCellType 协议的 enum。这个 enum 将包含所有可能的 cells 以及为注册和回收的每个 cell 的附加信息。

enum CellType: DKCellType {
    case `switch`(SwitchCellModel)

    var info: (cellClass: AnyClass, identifier: String) {
    switch self {
    case .switch:
        return (cellClass: SwitchCell.self, identifier: NSStringFromClass(SwitchCell.self))
    }
}

每个 cell 都需要一个对应的 model 进行配置。这个模型需要继承自通用类 DKCellModel<>,其中类型是您之前创建的 enum,所以目前是 DKCellModel<CellType>。然后您需要 override 属性 type 并将其设置为对应的 cell 类型。在这种情况下,CellType.switch 与类型为 SwitchCellModel 的关联值相关联,所以我们传递那里 self

final class SwitchCellModel: DKCellModel<CellType> {
    override var type: CellType { .switch(self) }

    let title: String
    var isOn: Bool

    init(title: String, isOn: Bool) {
    self.title = title
    self.isOn = isOn

    }
}

您有了 CellTypeCellModel 后,现在您需要的仅仅是您的 cell(显然)。每个 cell 都需要符合 DKTableConfigurableCell 协议,这将迫使您实现 configure(它在 cellForRow 中被调用),您还需要将模型 cast 到您的 cell 对应的模型,这样您就可以访问具体的属性。

extension SwitchCell: DKTableConfigurableCell {

    func configure<T>(with model: T) where T : DKCellModelProtocol {
        guard let model = model as? SwitchCellModel else { return assertionFailure() }
    
        titleLabel.text = model.title
        switchView.isOn = model.isOn
    }
}

现在您已经完成了。而且这就是您在控制器中实现无限类型 cell 所需要做的全部事情,甚至是单个生命周期。

lazy var dataSource = DKTableDataSource<CellType>(
    models: [
        TextFieldCellModel(title: "TextField 1", placeholder: "Placeholder 1"),
        SwitchCellModel(title: "Switch 1", isOn: true)
    ])

// in `viewDidLoad`
dataSource.registerCells(for: tableView)
tableView.dataSource = dataSource

DKTableDataSource 在初始化器中为所有 UITableViewDataSource 方法提供了闭包,如果需要,您可以在那里做一些额外的设置。

lazy var dataSource = DKTableDataSource<CellType>(
    models: [
        SwitchCellModel(title: "Switch 1", isOn: true),
    ],
    
    configureCell: { (model, cell) in
        
        if let cell = cell as? SwitchCell {
            cell.delegate = self
        }
        
        cell.configure(with: model)},
    
    titleForHeaderInSection: { _, section in "Section Header Title" },
    titleForFooterInSection: { _, section in "Section Footer Title" },
    canEditRowAtIndexPath: { _, indexPath in false },
    canMoveRowAtIndexPath: { _, indexPath in false }
)

包含更多区段的TableView

只需使用下面的 DKSectionedTableViewDataSource<>

lazy var section1DataSource = DKTableDataSource<CellType>(
    models: [
        DisclosureCellModel(title: "Disclosure 1", action: .action1),
        SwitchCellModel(title: "Switch 1", isOn: true),
    ])

lazy var section2DataSource = DKTableDataSource<CellType>(
    models: [
        BannerCellModel(imageName: "placeholder"),
    ])

lazy var dataSource = DKSectionedTableViewDataSource<CellType>(
    dataSources: [section1DataSource, section2DataSource]
)

// in `viewDidLoad`
dataSource.registerCells(for: tableView)
tableView.dataSource = dataSource

DKSectionedTableViewDataSource 还在初始化器中提供了闭包。

lazy var dataSource = DKSectionedTableViewDataSource<CellType>(
    dataSources: [section1DataSource, section2DataSource, section3DataSource],
    
    configureCell: { (model, cell) in
        
        if let cell = cell as? SwitchCell {
            cell.delegate = self
        }

        cell.configure(with: model)},
    
    sectionIndexTitles: { _ in ["A", "B", "C"] },

    sectionForSectionIndexTitle: { _, title, index in index }
)

集合视图

所有东西都可以与TableView相同,但您需要使用

  • DKCollectionConfigurableCell 而不是 DKTableConfigurableCell
  • DKCollectionDataSource 而不是 DKTableDataSource
  • DKSectionedCollectionDataSource 而不是 DKSectionedTableViewDataSource

所有情况都在示例项目中得到覆盖。

作者

Denis Kakaca, [email protected]

许可证

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