iOS工程师都知道tableview 在开发中是用得最多的,大部分页面几乎都可以用列表来做。但有没发现大量工作其实是重复的比如cell的注册,delegate数据源的匹配,cell的类型转换。接下来,我们需要将这些代理方法为tableview提供数据封装成数据模型。
数据源:dataSource[section[ rows],section[ rows]]
封装DataSource
1 | struct Section<Item> { |
Table Config
列表配置基本包含三项:重用标识,注册cell,配置cell1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41//table config
protocol ConfiguratorType {
associatedtype Item
associatedtype Cell: UITableViewCell
func reuseIdentifier(for item: Item, indexPath: IndexPath) -> String
func configuredCell(for item: Item, tableView: UITableView, indexPath: IndexPath) -> Cell
func registerCells(in tableView: UITableView)
}
//构建配置器。泛型Item, Cell
struct Configurator<Item, Cell: UITableViewCell>: ConfiguratorType {
typealias CellConfigurator = (Cell, Item, UITableView, IndexPath) -> Cell
let configurator: CellConfigurator
let reuseIdentifier = "\(Cell.self)"
func reuseIdentifier(for item: Item, indexPath: IndexPath) -> String {
return reuseIdentifier
}
func configure(cell: Cell, item: Item, tableView: UITableView, indexPath: IndexPath) -> Cell {
return configurator(cell, item, tableView, indexPath)
}
func registerCells(in tableView: UITableView) {
if let path = Bundle.main.path(forResource: "\(Cell.self)", ofType: "nib"),
FileManager.default.fileExists(atPath: path) {
let nib = UINib(nibName: "\(Cell.self)", bundle: .main)
tableView.register(nib, forCellReuseIdentifier: reuseIdentifier)
} else {
tableView.register(Cell.self, forCellReuseIdentifier: reuseIdentifier)
}
}
func configuredCell(for item: Item, tableView: UITableView, indexPath: IndexPath) -> Cell {
let reuseIdentifier = self.reuseIdentifier(for: item, indexPath: indexPath)
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! Cell
return self.configure(cell: cell, item: item, tableView: tableView, indexPath: indexPath)
}
}
多类型cell配置器
假如我们的一个业务列表由两种cell组成:TableCell,NibCell。那么我们提供重用标识,配置cell时候就需要做好枚举判断。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42enum CellType {
typealias Model = String
typealias AnotherModel = String
case cell(Model)
case anotherCell(AnotherModel)
}
class TableCell: UITableViewCell {
}
class NibCell: UITableViewCell {
}
struct MoreCellsConfigurator: ConfiguratorType {
let cellConfigurator: Configurator<CellType.Model, TableCell>
let anotherCellConfigurator: Configurator<CellType.AnotherModel, NibCell>
func reuseIdentifier(for item: CellType, indexPath: IndexPath) -> String {
switch item {
case .cell:
return cellConfigurator.reuseIdentifier
case .anotherCell:
return anotherCellConfigurator.reuseIdentifier
}
}
func configuredCell(for item: CellType, tableView: UITableView, indexPath: IndexPath) -> UITableViewCell {
switch item {
case .cell(let model):
return cellConfigurator.configuredCell(for: model, tableView: tableView, indexPath: indexPath)
case .anotherCell(let model):
return anotherCellConfigurator.configuredCell(for: model, tableView: tableView, indexPath: indexPath)
}
}
func registerCells(in tableView: UITableView) {
cellConfigurator.registerCells(in: tableView)
anotherCellConfigurator.registerCells(in: tableView)
}
}
使用多cells配置器
1 | class ExampleTableViewController<Item, Cell: UITableViewCell>: UITableViewController{ |
demo控制器举例
1 | extension UIViewController { |