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
.