如何在CellForRowAt中高效出队自定义TableViewCell,避免违反开闭原则?
优化UITableView多Cell实现方案(无大量if-else+符合开闭原则)
针对你当前用大量if-else判断Cell类型的问题,推荐用CellViewModel协议+统一数据数组的方式实现,完全符合开闭原则,新增Cell时无需修改ViewController核心逻辑。
步骤1:定义CellViewModel协议
先定义一个协议,让所有Cell对应的数据模型都遵循这个协议,协议包含Cell的标识和配置Cell的方法:
protocol TableCellViewModel { var cellIdentifier: String { get } func configure(cell: UITableViewCell) }
步骤2:为每个自定义Cell实现对应的CellViewModel
把原来分散在cellForRowAt里的配置逻辑(包括特殊的UI调整,比如SecondCell的高度设置)转移到对应的CellViewModel中:
FirstCell对应的ViewModel
struct FirstCellViewModel: TableCellViewModel { let data: FirstCellData // 你原来的FirstCell数据结构体 var cellIdentifier: String { return "firstCell" } func configure(cell: UITableViewCell) { guard let firstCell = cell as? FirstCell else { return } firstCell.configure(data: data) } }
SecondCell对应的ViewModel
struct SecondCellViewModel: TableCellViewModel { let data: SecondCellData // 你原来的SecondCell数据结构体 var cellIdentifier: String { return "secondCell" } func configure(cell: UITableViewCell) { guard let secondCell = cell as? SecondCell else { return } secondCell.configure(data: data) // 把原来在ViewController里的高度调整逻辑移到这里 secondCell.productSpecificationsTableViewHeight.constant = secondCell.productSpecificationsTableView.contentSize.height } }
步骤3:修改主ViewModel的数据源结构
把原来单个的firstCellData、secondCellData改成一个TableCellViewModel类型的数组,按Cell的显示顺序排列:
class MainViewModel { var cellViewModels: [TableCellViewModel] = [] // 初始化或数据加载时,按顺序添加各个Cell的ViewModel func loadData() { // 示例:添加FirstCell的ViewModel let firstData = FirstCellData(/* 初始化数据 */) cellViewModels.append(FirstCellViewModel(data: firstData)) // 添加SecondCell的ViewModel let secondData = SecondCellData(/* 初始化数据 */) cellViewModels.append(SecondCellViewModel(data: secondData)) // 后续新增Cell,直接在这里添加对应的ViewModel即可 } }
步骤4:简化ViewController的cellForRowAt方法
现在不需要任何if-else判断,直接从ViewModel的数组中取对应的数据模型,完成Cell的出队和配置:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cellViewModel = viewModel.cellViewModels[indexPath.row] let cell = tableView.dequeueReusableCell(withIdentifier: cellViewModel.cellIdentifier, for: indexPath) cellViewModel.configure(cell: cell) return cell }
新增Cell的流程(完全符合开闭原则)
当需要新增自定义Cell时,只需要做3件事:
- 创建新的Cell类(比如
ThirdCell),实现自己的configure(data:)方法 - 创建对应的
ThirdCellViewModel,遵循TableCellViewModel协议,实现标识和配置逻辑 - 在主ViewModel的
loadData()方法中,把ThirdCellViewModel添加到cellViewModels数组里
整个过程不需要修改ViewController的任何代码,完全符合对扩展开放,对修改关闭的开闭原则。
内容的提问来源于stack exchange,提问作者Rohit
相关产品推荐
相关产品推荐

