In this tutorial, we’ll be developing an iOS Application using Swift that has a single iOS UITableView with two different types of UITableViewCells.
Multiple Cells inside a TableView are commonly seen in the Facebook newsfeed application which hosts cells largely grouped into three types – Status Posts, Image Posts and Video Posts.
iOS UITableView with different type of cells
We’ll be creating an application that displays two types of cells. First, that displays country flag and name. Second, that displays population for the country. We’ll be populating the data in the UITableView from a generic array.
Let’s start our XCode and select a Single View Application template. We’ll setup our UI in Main.storyboard
using Autolayout as shown below.
- Adding a TableView and setting up its constraints. Displaying two prototype cells.
- Adding a
UIImageView
and Label in the first prototype cell followed by setting their constraints. - Setting up the second prototype cell followed by defining the identifiers and class name for each UITableViewCell.
- Adding the references of the views in the ViewController and Custom Cells.
The code for the ViewController.swift
file is given below.
import UIKit
class CustomCountryCell: UITableViewCell{
@IBOutlet var countryName: UILabel!
@IBOutlet var countryIcon: UIImageView!
}
class CustomPopulationCell: UITableViewCell{
@IBOutlet var countryPopulation: UILabel!
}
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet var tableView: UITableView!
var tableData = ["Australia", 24.13, "Canada", 36.29 ,"China", 1379, "India", 1324, "United States of America", 323.1] as [Any]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.dataSource = self
tableView.delegate = self
tableView.tableFooterView = UIView()
tableView.rowHeight = 60
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let string = self.tableData[indexPath.row] as? String
{
let cell:CustomCountryCell = self.tableView.dequeueReusableCell(withIdentifier: "customCountryCell") as! CustomCountryCell
cell.countryName?.text = string
cell.countryIcon?.image = UIImage(named:string)
return cell
}
else if let population = self.tableData[indexPath.row] as? Any, population is Double || population is Int {
let cell:CustomPopulationCell = self.tableView.dequeueReusableCell(withIdentifier: "customPopulationCell") as! CustomPopulationCell
cell.countryPopulation?.text = "Population is (population) million"
return cell
}
return UITableViewCell()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
}
Following are the notable things present in the ViewController class.
-
- We’ve implemented the two protocols present in the UITableView class i.e. UITableViewDelegate and UITableViewDataSource
.
tableData
is a generic array that holds String, Double and Integer types. The string element is used to set the Image(the image assets have the same name set in the Assets folder) and country name.tableView.tableFooterView = UIView()
removes the empty cells after the last populated row in the UITableView.tableView.rowHeight = 60
sets the row height for each UITableViewCell.- Cell of the type CustomCountryCell is added in the UITableView if the current element in the
tableData
is a String. - To check whether the current element in the
tableData
is of the type Double or Integer the following condition is used :if let population = self.tableData[indexPath.row] as? Any, population is Double || population is Int { }
In the above code snippet, the
,
acts as a where clause. The condition reads as : “ifself.tableData[indexPath.row]
is a valid element, typecast it to Any and check whether it is of the type Double OR type Int”.Note: The above condition can be written in following way too.
else if let population = self.tableData[indexPath.row] as? Double{ let cell:CustomPopulationCell = self.tableView.dequeueReusableCell(withIdentifier: "customPopulationCell") as! CustomPopulationCell cell.countryPopulation?.text = "Population is (population) million" return cell } else if let population = self.tableData[indexPath.row] as? Int{ let cell:CustomPopulationCell = self.tableView.dequeueReusableCell(withIdentifier: "customPopulationCell") as! CustomPopulationCell cell.countryPopulation?.text = "Population is (population) million" return cell }
return UITableViewCell()
is used to add a default empty cell if none of the conditions match.didSelectRowAt
function is used to add the click animation on each TableView row.
The output of the above application in action is given below.
This brings an end to this tutorial. A similar implementation for Android using RecyclerView is given here. You can download the iOS TableViewMultipleCellTypes Project from the link below.
Reference: Apple Documentation