Dynamic layout - Self Sizing UITableViewCell
How to easily create a dynamic UITableViewCell using constraint set in Storyboard that have a UIImageView and UILabel. These details could possibly be updated from an api call like most app out there.
Overview
We will be creating a simple coffee apps that explains the different kind of coffees. The app will have a coffee image and its descriptions in each UITableViewCell. The images will be in different sizes and the number of characters in descriptions will be different as well.
A few screenshots showing the coffees app:

Setup Constraint
Create a custom UITableViewCell with a UIImageView and UILabel in it.
Set constraints for UIImageView base on the screenshot below.

And follow the following screenshot for UILabel.

Configure UITableView
Next, we will need to let UITableView know that we want the rowHeight to be automatic determined.
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 140
}
estimatedRowHeight not only help with the improve of performance when loading tableView but it also need to be set to any value bigger than 0. By default the value is 0 which means there is no estimate.
A more details description from Apple:
Providing a nonnegative estimate of the height of rows can improve the performance of loading the table view. If the table contains variable height rows, it might be expensive to calculate all their heights when the table loads. Using estimation allows you to defer some of the cost of geometry calculation from load time to scrolling time.
When you create a self-sizing table view cell, you need to set this property and use constraints to define the cell’s size.
The default value is 0, which means there is no estimate.
Custom class: Coffee and CoffeeTableViewCell
Next we will create a custom CoffeeTableViewCell class and Coffee struct. Our Coffee struct will be holding a imageName and description of the coffee.
struct Coffee {
let imageName: String
let description: String
init(imageName: String, description: String) {
self.imageName = imageName
self.description = description
}
}
In storyboard, update the cell to our custom class CoffeeTableViewCell. Then create an @IBOulet for the UIImageView and UILabel .
In the CoffeeTableViewCell we will create a configure function to update its IBOutlet with a Coffee model.
class CoffeeTableViewCell: UITableViewCell {
@IBOutlet weak var coffeeImageView: UIImageView!
@IBOutlet weak var coffeeDescLabel: UILabel!
func configure(coffee: Coffee) {
coffeeImageView.image = UIImage(named: coffee.imageName)
coffeeDescLabel.text = coffee.description
}
}
In our controller CoffeesViewController
We will have an @IBOulet tableView hookup from storyboard. We will also add getCoffeeData() at the end of viewDidLoad()
class CoffeesViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
let coffeeService = CoffeeService()
var coffees = [Coffee]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 140
getCoffeeData()
}
func getCoffeeData() {
coffeeService.getCoffeeData() { coffees in
self.coffees = coffees
self.tableView.reloadData()
}
}
}
CoffeeService is just a fake service class with a completion func that return [Coffee] like it is being fetched from a api call.
Lastly, setup the datasource with the required func. Remember to hook up the delegate and datasource from tableView to CoffeesViewController in the storyboard.
extension CoffeesViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return coffees.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CoffeeTableViewCell") as! CoffeeTableViewCell
let coffee = coffees[indexPath.row]
cell.configure(coffee: coffee)
return cell
}
}
Sample Project
A sample project could be download here.
Thats all you need to setup a self sizing UITableViewCell. Ensure that that the correct constraint is set in storyboard, rowHeight and estimatedRowHeight is also updated for tableView.