Implementation of generic data sources for both collection and table views.
This solution was based on the existing Florian Kugler's approach
Implementing a data source generaly requires repetitive and boilerplate code.
This solution proposes a different approach to simplify the definition of your static collection's content.
Definition of the view models for sections and rows and definition of the cell type for each kind.
The cell identifier can dependent on the cell type or can be improved with some other approach. I decided to not include it here because we are not performing cell registration and it depends on that.
struct SectionViewModel: Section {
enum RowType {
case rowType1(viewModel: Type1TableViewCellModel)
case rowType2(viewModel: Type2TableViewCellModel)
case rowType3(viewModel: Type3TableViewCellModel)
}
var rows: [RowType]
}
struct FirstSectionViewModel {
static func make() -> SectionViewModel {
let rows = [SectionViewModel.RowType.rowType1(viewModel: Type1TableViewCellModel()),
SectionViewModel.RowType.rowType2(viewModel: Type2TableViewCellModel())]
return SectionViewModel(rows: rows)
}
private init() {}
}
final class ViewController: UIViewController {
private var dataSource: GenericTableViewDataSource<SectionViewModel>!
(...)
private func configureTableView() {
// Cells registration code
(...)
// Create cells descriptor
let cellDescriptor: (SectionViewModel.RowType) -> TableCellDescriptor = { rowType in
switch rowType {
case .rowType1(let viewModel):
return TableCellDescriptor(cellIdentifier: String(describing: Type1TableViewCell.self)) { (cell: Type1TableViewCell) -> Void in
cell.configure(with: viewModel) // cell based implementation
}
case .rowType2(let viewModel):
return TableCellDescriptor(cellIdentifier: String(describing: Type2TableViewCell.self)) { (cell: Type2TableViewCell) -> Void in
cell.configure(with: viewModel) // cell based implementation
}
case .rowType3(let viewModel):
return TableCellDescriptor(cellIdentifier: String(describing: Type3TableViewCell.self)) { (cell: Type3TableViewCell) -> Void in
cell.configure(with: viewModel) // cell based implementation
}
}
}
self.dataSource = GenericTableViewDataSource(items: [FirstSectionViewModel.make()], cellDescriptor: cellDescriptor)
self.tableView.dataSource = self.dataSource
}
}