DEV Community

Cover image for UITableView with multiple kinds of cells (also works on UICollectionView)
Fabrício Masiero
Fabrício Masiero

Posted on

1 2

UITableView with multiple kinds of cells (also works on UICollectionView)

Hi everyone =D



I will show in this article how to use multiple types of cells in your UITableView or UICollectionView.
A lot of developers do that in the wrong way, using sections or rows to present another kind of cell.

This tutorial will be separated on 3 fronts:

  • 1 - Create a model
  • 2 - Register cells on your controller
  • 3 - Organize it on cellForRow

Creating a model

First of all, I create a simple model to populate my table.

public enum VehicleType {
case car
case moto
case bike
}
public struct Vehicle {
public let manufacturer: String
public let model: String
public let type: VehicleType
public let year: Int
public let imageName: String
init(manufacturer: String, model: String, type: VehicleType, year: Int, imageName: String) {
self.manufacturer = manufacturer
self.model = model
self.type = type
self.year = year
self.imageName = imageName
}
}
view raw Vehicle.swift hosted with ❤ by GitHub

The secret of this model is the enum VehicleType. That changes everything!

Creating and register cell on table

After that, I create 3 kinds of cell:

Bike Cell

Bike Cell
Car Cell
Car Cell

And finally, Motorbike Cell
Moto Cell

private func registerCell() {
let carCell = UINib(nibName: "CarTableViewCell", bundle: Bundle.main)
let motoCell = UINib(nibName: "MotoTableViewCell", bundle: Bundle.main)
let bikeCell = UINib(nibName: "BikeTableViewCell", bundle: Bundle.main)
tableView.register(carCell, forCellReuseIdentifier: "carCell")
tableView.register(motoCell, forCellReuseIdentifier: "motoCell")
tableView.register(bikeCell, forCellReuseIdentifier: "bikeCell")
}

And create an array of vehicles:

private func setVehicles() {
vehicles = [
Vehicle(manufacturer: "Jeep", model: "Willys", type: .car, year: 1970, imageName: "jeep-willys"),
Vehicle(manufacturer: "Harley Davidson", model: "Iron 883", type: .moto, year: 2018, imageName: "harley-davidson-iron883"),
Vehicle(manufacturer: "Bianchi", model: "Super Pista", type: .bike, year: 2015, imageName: "bianchi-super-pista"),
Vehicle(manufacturer: "Land-Rover", model: "Defender 90", type: .car, year: 1999, imageName: "land-rover-defender90")
]
tableView.reloadData()
}
view raw Vehicles.swift hosted with ❤ by GitHub

Set cell on cellForRow

Ok, we are almost done! What we need to do right now is configure our cellForRow atIndexPath or itemForRow atIndexPath.
Write an switch case to determine what kind of cell table will present. Like this example:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let vehicle = vehicles[indexPath.row]
switch vehicle.type {
case .bike:
let cell = tableView.dequeueReusableCell(withIdentifier: "bikeCell") as! BikeTableViewCell
cell.set(vehicle: vehicle)
return cell
case .moto:
let cell = tableView.dequeueReusableCell(withIdentifier: "motoCell") as! MotoTableViewCell
cell.set(vehicle: vehicle)
return cell
default:
let cell = tableView.dequeueReusableCell(withIdentifier: "carCell") as! CarTableViewCell
cell.set(vehicle: vehicle)
return cell
}
}

But, if you saw, each cell has a different size. Ok, let's do the same thing on heightForRow atIndexPath

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let vehicle = vehicles[indexPath.row]
switch vehicle.type {
case .bike:
return 180
case .moto:
return 120
default:
return 243
}
}

And that's it! Simple, beautiful, and very easy!

I don't prepared a beautiful layout on these cells, but, take a look, we have 3 different cells on the same Table or Collection:

View Controller

Download source code here =D

I hope I have helped everyone looking for this change.
If you would like to extend the discussion, call me on Twitter

Happy Coding :)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (1)

Collapse
 
steven_thompson_144188290 profile image
Steven Thompson

But all those switch statements are now unnecessay. Each model can now handle this.

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs