Cell dynamic modeling of TableView based on MVC

This paper mainly introduces the MVC mode, split TableView agent, to achieve different data sources dynamically create different Cell.

The file structure is as follows:

Cell dynamic modeling of TableView based on MVC
file structure icon.Png

File structure analysis


Here is the page of the Controller, mainly responsible for the logic load and set TableView proxy

  • Items
    a item corresponds to a Cell, data unit package
  • DataSource
    custom DataSource class, used to implement the UITableViewDataSource TableView agent, and the distribution of the item and Cell relationship model receive data, packaged into item, and adding an array of
  • Cells
    custom Cell one-to-one correspondence with item

Key analysis

TableView has two agents, which are UITableViewDelegate and UITableViewDataSource, where the need to focus on UITableViewDataSource for some customization.


First of all, we define an agreement LittleHTableViewDataSourcePotocol as follows:

Public protocol LittleHTableViewDataSourcePotocol:NSObjectProtocol, UITableViewDataSource func tableView (_ {tableView:UITableView, objectForRowAt, indexPath:IndexPath) -> AnyObject func tableView (tableView: _? UITableView, cellClassForObject object: AnyObject LittleHTableViewBaseCell.Type func (->); tableView tableView: UITableView indexPathForObject object: AnyObject _, ->); IndexPath tableView (tableView: _? Func UITableView, cell:UITableViewCell willAppearAtIndexPath, indexPath: IndexPath -> Void)}

Then we declare a custom DataSource class to implement the LittleHTableViewDataSourcePotocol protocol

Public class LittleHTableViewDataSource: NSObject, LittleHTableViewDataSourcePotocol public var items: NSArray {public init (items: NSArray) = {self.items items} / / MARK: / / MARK: -LittleHTableViewDataSourcePotocol public func tableView (_ method tableView: UITableView, objectForRowAt indexPath: IndexPath -> AnyObject) {if indexPath.row? < self.items.count return self.items.object (at: indexPath.row) {as AnyObject else}? {return nil}} public func tableView (tableView: UITableView cellClassForObject object: AnyObject _, -> LittleHTableViewBaseCell.Type) {return LittleHTableViewBaseCell.self} public func tableView (TA _ BleView: UITableView, indexPathForObject object: AnyObject -> IndexPath) {return} public? Nil func tableView (_ tableView: UITableView, cell:UITableViewCell, willAppearAtIndexPath indexPath: IndexPath -> Void) {} / / MARK: / / MARK: -UITableViewDataSource func tableView (tableView: public _ UITableView numberOfRowsInSection section:, Int ->); Int self.items.count public func tableView {return} (_ tableView: UITableView, cellForRowAt indexPath: IndexPath -> UITableViewCell) {let = object:AnyObject? Self.tableView (tableView, objectForRowAt: indexPath var cell1:UITableViewCell if let obj1) {let cellClass:LittleHTableViewBaseC = object Ell.Type = self.tableView (tableView cellClassForObject: obj1) let identifier:String = cellClass.LittleHIdentifier (VaR) cell:UITableViewCell? TableView.dequeueReusableCell (withIdentifier: identifier) = if cell = = nil {cell = cellClass.init (style: UITableViewCellStyle.default, reuseIdentifier: identifier = cell cell1)}!} else {cell1 = LittleHTableViewBaseCell (style: UITableViewCellStyle.default, reuseIdentifier: Nil) if cell1 is LittleHTableViewBaseCell {let} cell2 = cell1 as! LittleHTableViewBaseCell cell2.setObject (object) return cell1 public func numberOfSections}} (in TableView: UITableView -> Int) {return 1} open func tableView (tableView: UITableView sectionForSectionIndexTitle _, title: String, at index: Int -> Int) {if let view1 = tableView.tableHeaderView index = = 0 {if {tableView.scrollRectToVisible (view1.bounds animated: false) return -1}} / / let index2 = advance (title.startIndex, 1) var index2:String.Index title.startIndex = index2 = title.index (index2, offsetBy: 1) let letter:String = title.substring (to: index2) let sectionCount:Int = tableView.numberOfSections var i:Int = 0 for _ in 1 sectionCount let section: S {... Tring = (tableView.dataSource?.tableView (tableView titleForHeaderInSection: I)!)! If section.hasPrefix (letter) {return}} = 1 I I if index > sectionCount return sectionCount {- 1} {return}}} index else

In our own definition of the DataSource which can be seen in the UITableViewDataSource has been achieved, we through the LittleHTableViewDataSourcePotocol protocol

Func tableView (tableView: UITableView cellClassForObject object: AnyObject _, -> LittleHTableViewBaseCell.Type)

Method to obtain a specific Cell classType, and then create this type of Cell, and through the LittleHTableViewDataSourcePotocol protocol

Func tableView (tableView:UITableView _, objectForRowAt -> AnyObject indexPath:IndexPath)?

Methods to obtain the data of Cell, and to evaluate the data in Cell setObject method.

Controller key code

Where we use tableView, set the tableView proxy of UITableViewDataSource to the object of this class. Such as:

Public var dataSource: LittleHTableViewDataSource? Return _dataSource set{if {get{} newValue! = _dataSource {_dataSource newValue} = if let tableView1 = self.tableView tableView1.dataSource = _dataSource (tableView1.reloadData) {}}}

We hope that the height of the Cell can return within the Cell, the best time in the item data package directly calculate the height of the Cell, and then return the height of the task to achieve the following UITableViewDelegate method will return the transfer to Cell

Open func tableView (tableView: UITableView heightForRowAt indexPath: IndexPath _, -> CGFloat) {if (tableView.dataSource is LittleHTableViewDataSource) {let dataSource:LittleHTableViewDataSource = tableView.dataSource? As? LittleHTableViewDataSource if let D1 = dataSource {let object = d1.tableView (tableView objectForRowAt: indexPath) if let obj1 = object {let t1:LittleHTableViewBaseCell.Type = d1.tableView (tableView, cellClassForObject:, obj1) return t1.tableView (tableView rowHeightForObject: obj1)}}}} return 44


Cell needs to be implemented

Public func setObject (obj:AnyObject -> Void _?)

To get data

Public class func tableView (tableView: UITableView rowHeightForObject object: AnyObject _, -> CGFloat)

Get height


Public class LittleHIdentifier () -> String (func)

Set reuseIdentifier

The main idea of the TableView UITableViewDataSource Cell construction can be based on classType to dynamically build the data type item and Cell one-to-one correspondence.

Demo address