Protocol oriented write TableView

TableView is a commonly used component, and it’s more complicated. Flexible application can not only improve the efficiency of development, but also bring great convenience to the later stage maintenance. The use of TableView can not avoid dealing with its data sources and protocols, although this design allows them to decouple from the TableView, but at the same time it also results in poor data dispersion and maintenance.

Very typical example is in cellForRowAt or didSelectRowAt do a variety of case judgment, this kind of writing in the later maintenance is easy to cause mistakes. This article introduces a protocol oriented approach that gracefully solves this problem, but this method applies only to static TableView.

All of the Tableview protocol and proxy method, there is a common point, are associated with IndexPath, we can try to subscript, some commonly used methods of agent / protocol, data package to a data structure, then the structure of the unified management.

Encapsulate the data that the configuration structure needs to provide as an agreement that includes cell reuse, ID, cell class names, cell selected click events, cell heights, and so on.

Protocol CellConfigurable var reuseIdentifier: {String {get} var {get} cellClass: AnyClass var selection: Selectable? Var height: {get} CGFloat {get} func configureCell (cell: UITableViewCell _)}

Selectable is a package that clicks on the Cell event.

Protocol Selectable func didSelectedIndexPath (indexPath: _ {IndexPath})

That’s not enough. We just define generic data. Cell can display a wide variety of content. You can use the ViewModel structure to bind data to Cell.

Protocol, CellViewModel, {associatedtype, ViewModel, VaR, viewModel:, ViewModel, {get}, func, configure (viewModel:, ViewModel)}

Let Cell implement the CellViewModel protocol.

Based on the above two protocols, we can construct the data structure for configuring Cell.

Struct CellConfigurator< Cell: UITableViewCell> where: CellConfigurable Cell: CellViewModel let viewModel: Cell.ViewModel let reuseIdentifier: {String = NSStringFromClass (Cell.self) let cellClass: AnyClass Cell.self let selection: = Selectable? Let height: CGFloat init (viewModel: Cell.ViewModel, height: CGFloat, selection: Selectable? = Nil) {self.viewModel = viewModel self.height = height self.selection = selection func configureCell (_} cell: UITableViewCell if let cell) {cell = as? Cell (viewModel: viewModel) {cell.configure}}}

According to the above foreshadowing, we will complete a TableView based interface.

Protocol oriented write TableView

The interface is made up of switches and Detail. The first thing you need to do is to define the ViewModel, which must contain all the content that the style Cell needs to display, as well as the control’s events.

Struct, TableViewCellViewModel, {let, title:, String, let, String, image:, let, UIImage, let, isOn:, Bool, let, detail:, action: ((Bool) ->, Void)}?

This is just a Demo, a concrete and complex case that defines multiple Cell and corresponding ViewModel in style.

This requires only the creation of a data source in the controller

Let viewModel = TableViewCellViewModel (title: title, detail: detail, image: image, isOn: false, action: switchAction) let configurator = CellConfigurator< TableViewCell> (viewModel: viewModel, height: 44, selection: selectionActions[index]) dataArray.append (configurator)

In the end, you don’t need to consider specific Cell types and what the corresponding subscript is:

Func tableView (tableView: UITableView cellForRowAt indexPath: IndexPath _, -> UITableViewCell) {let configurator = dataArray[indexPath.row] let cell = tableView.dequeueReusableCell (withIdentifier: configurator.reuseIdentifier, for: indexPath) configurator.configureCell (cell) return cell}

This is the complete Demo: ProtocolTableView