How to Create Dynamic Table Views in Swift


TableView is a common component while developing a user interface in Swift. A TableView ​is essentially an easy way to display a list of items. Both images and text can be listed. We used TableView for developing screens of registration page and dashboard.

What are Rows and Sections

A table view consists of rows and sections. The sections and rows of the table view are basically represented as enums. You can check this post as a reference to use table and rows as enums.

However, the feature we were building required one single screen with dynamic table view where the sections could be added or removed and the cells shown or hidden. It is difficult to achieve this behavior using enums and using a library for one single screen wasn’t attractive either. So, we resorted to a different approach.

How to create a dynamic table view?

First, we declare a protocol for every section of the table view:

protocol DynamicSection: class {
    var rows: [DynamicRow] { get set }
    var title: String? { get set }
}

 

Similarly, for a row:
protocol DynamicRow: class {
    func getCellFor(_ tableView: UITableView, indexPath: IndexPath) -> UITableViewCell
    func didSelectRow()
}// empty implementation so that only interested cells need to implement this functionextension DynamicRow {
    func didSelectRow() {}
}

 

The getCellFor function is called during cellForRowAtIndexPath and will return a UITableViewCell. The didSelectRow function is called during didSelectRowAtIndexPath callback. As all rows won’t be selectable, the empty implementation frees us from needing to implement it in every cell type.

It’s time to create a cell to use our dynamic sections and rows. Here’s a basic cell with just a label:

class BasicCell: UITableViewCell {
    @IBOutlet var label: UILabel!
}

 

For every cell, a wrapper class is required which implements the DynamicRow protocol and notifies the view controller of user interaction events like cell tap, button clicked inside cell, etc. Below is the wrapper for BasicCell above:

class BasicCellWrapper: DynamicRow {
  var title: String
  var completion: BasicCellTapCompletion?
  
  init(title: String, completion: BasicCellTapCompletion?) {
    self.title = title
    self.completion = completion
  }  func getCellFor(_ tableView: UITableView, indexPath: IndexPath) ->   UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier:   String(describing: BasicCell.self), for: indexPath) as! BasicCell
    cell.label.text = title
    return cell
  }  func didSelectRow() {
    completion?(title)
  }}typealias BasicCellTapCompletion = (String) -> ()

 

Nothing fancy going on here, the wrapper takes all the information it needs to display the cell in its initializer. The completion handler notifies the view controller that the cell has been selected.

Now let’s implement a basic section that takes a title and an array of rows:

class BasicSection: DynamicSection {
  var rows: [DynamicRow]
  var title: String?  init(title: String?, rows: [DynamicRow]) {
    self.title = title
    self.rows = rows
  }
}

 

Now, we are ready to implement our basic row and section it in our tableview controller.

var sections: [DynamicSection] = [] let mangoCell = BasicCellWrapper(title: "Mango") { [weak self] text in
  print(text) // prints Mango
} 
let fruitsSection = BasicSection(title: "Fruits", rows: [appleCell])
sections.append(fruitsSection)

Summary:

  1. The wrappers should not be a struct as they can be copied during assignment operation and should not hold the cell in getCellFor method.
  2. Don’t implement DynamicRow protocol in any class extending UITableViewCell because then you will need to programmatically create the cells instead of dequeuing them. It’s a bad idea.

Dive deeper into real-life engineering stories.

More in Blogs

How to Automate your Work From Home: Puppeteer Use Case InsightsTechnology

How to Automate your Work From Home: Puppeteer Use Case

In this article, we will achieve task automation by writing some code using Node and we will make use of the somewhat non-traditional method of using a headless browser.

Read more
8 DevOps Tools and Services We Love Technology

8 DevOps Tools and Services We Love

The core focus of any DevOps team is evolving and improving products rapidly. At Leapfrog, we value the speed at

Read more
How We Moved Towards Serverless Architecture Technology

How We Moved Towards Serverless Architecture

The scalability, flexibility and reduced cost promised by serverless architecture resulted in a massive growth rate of 75% compared to

Read more