Self-Sizing Table View Cells

Learn how to enable self-sizing table view cells and make them resize on-demand while supporting Dynamic Type. By Chuck Krutsinger .

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 2 of 3 of this article. Click here to view the first page.

Configuring the Table View

First, you need to configure the table view to use AuteurTableViewCell.

Open AuteurListViewController.swift. Replace tableView(_:cellForRowAt:) with the following:

func tableView(
  _ tableView: UITableView,
  cellForRowAt indexPath: IndexPath
) -> UITableViewCell {
  // 1
  let cell = tableView.dequeueReusableCell(
    withIdentifier: "AuteurCell", for: indexPath)
  // 2
  if let cell = cell as? AuteurTableViewCell {
    let auteur = auteurs[indexPath.row]
    cell.bioLabel.text = auteur.bio
  }
  return cell
}

The code above is pretty straightforward. In it, you:

  1. Dequeue an AuteurCell. This is the identifier from the storyboard.
  2. Set the bio text from the current row of the auteurs array and return the cell.

Still in AuteurListViewController.swift, add these two lines of code at the end of viewDidLoad():

tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 600

Setting the row height to UITableView.automaticDimension tells the table view to use the Auto Layout constraints and the contents of its cells to determine each cell’s height.

For the table view to do this, you must also provide estimatedRowHeight. In this case, 600 is a roughly estimated value that works well in this particular instance.

For your own projects, you’ll need to determine a good estimate of the average height. Any value will work, but the accuracy of the estimate affects the efficiency of the layout.

Build and run. You’ll now see each auteur’s full bio.

First working auto layout for auteur cell showing the full bio text for the auteur

That looks better! But wouldn’t a moody dark background make this app even more dramatic?

Adding a Background

Open Main.storyboard. In the table view of Auteurs Scene, select AuteurCell. In the Attributes inspector, click the Background drop-down menu:

Select the AuteurCell background color property

Select AuteursBackground for a nice black-ish background — pure black is not cool enough for auteurs. :]

In the same scene, set the same background color for Table View and View.

Now, select Bio Label. Set the text color to System Gray 4 Color so the text will stand out against the new background color.

Set bio label color to system gray 4

You want the navigation header to have the same background color, so open AppDelegate.swift and paste this code after var window: UIWindow?:

func applicationDidFinishLaunching(_ application: UIApplication) {
  let appearance = UINavigationBarAppearance()
  appearance.configureWithOpaqueBackground()
  appearance.backgroundColor = UIColor(named: "AuteursBackground")
  appearance.titleTextAttributes = [
    NSAttributedString.Key.foregroundColor: UIColor.systemGray2
  ]
  appearance.largeTitleTextAttributes = [
    NSAttributedString.Key.foregroundColor: UIColor.systemGray2
  ]
  UINavigationBar.appearance().standardAppearance = appearance
  UINavigationBar.appearance().compactAppearance = appearance
  UINavigationBar.appearance().scrollEdgeAppearance = appearance
}

The code above defines the appearance of UINavigationController throughout your app. It will give it an opaque background using AuteursBackground as the background color and System Gray 2 as the text color.

Build and run. It’ll look like this:

The Auteurs list and navigation bar now have the same dark color.

Such drama!

Adding More User Interfaces

It’s nice to read the entire bio of each artist, but there’s more data to show: the artist’s name, image and the source of the information. These additional pieces of data will make the app look much better.

Your next goal is to add an image view to AuteurTableViewCell, a label for the auteur’s name and a label for the source of the photo.

Open AuteurTableViewCell.swift. Add the following properties:

@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var sourceLabel: UILabel!
@IBOutlet weak var auteurImageView: UIImageView!

These UI elements will display the auteur’s name, information source and image.

Open Main.storyboard. In bio label, remove the constraints you added earlier.

You can select and remove all four constraints in the Document Outline.

Delete all of the bio label constraints

Before adding more elements, you’ll want some elbow room. Select AuteurCell from the Document Outline. Then, in the Size inspector, change the row height to 450.

Set the AuteurCell row height to 450

Adding Views to the Cell

Now, you’ll fill up the space you just added. From the Library, drag:

  • An Image View into the cell.
  • A Label into the cell. Set the text to Name and color to System Gray 4.
  • Another Label into the cell. Set the text to Source and font size to System 13.0 and color to System Gray 4.

Next, connect the outlets for the new image view and labels:

Connect the AuteurCell elements to their AuteurTableViewCell outlets.

Adding New Constraints on a Stack View

Instead of creating constraints for every view, you’re going to use a stack view to limit the number of constraints. Embed the labels and image view from AuteurTableViewCell in a stack view.

In the Document Outline, order the elements from top to bottom as follows within the stack view:

  1. Image View
  2. Name Label
  3. Bio Label
  4. Source Label

Stack view with elements ordered

Select the stack view. In the Attributes inspector, set the alignment to Fill and spacing to 8.

Stack view settings

Add the following constraints to the stack view:

  • 0 points from the top and bottom margins.
  • 8 points from the leading and trailing margins.

Add the following constraints to the image view:

  • 1:1 width-to-height aspect ratio.

Aspect ratio width to height one to one

Just like that, you’ve pinned the edges of the stack view its superview’s edges. Plus, you’ve ensured a 1:1 width-to-height aspect ratio with the image view.

However, the labels have equal vertical content hugging priority and it’s ambiguous to Auto Layout to prioritize which label should shrink or expand over the other. You’ll inform Auto Layout about this next.

Setting the Hugging Priorities

You’ll set the hugging vertical priorities for the name label and bio label.

Select Name Label and, in the Size inspector, scroll down until you see Content Hugging Priority.

By default, horizontal and vertical content hugging priorities are 251. Change the name label’s vertical content hugging priority to 253.

Setting name label vertical content hugging priority

Now, select the Bio Label and set its Vertical priority to 252.

Not exactly. Setting a higher priority on content hugging means the view will resist growing larger than its intrinsic size. You told the storyboard to make your cell 450 points tall, which is larger than the intrinsic size of your views. Setting a vertical content hugging priority tells Xcode which view to expand if it needs to fill the space.

Note: Wait, what’s with all the hugging? Is this a romance picture?

You have the layout of your table view cell without all that much cognitive efforts. However, your UI wouldn’t be complete without populating the new views.

Populating the New Views

Now, you’ll populate the views. Open AuteurTableViewCell.swift. Add the following method:

func configure(
  name: String,
  bio: String,
  sourceText: String,
  imageName: String
) -> AuteurTableViewCell {
  // 1
  nameLabel.text = name
  bioLabel.text = bio
  sourceLabel.text = sourceText
  auteurImageView.image = UIImage(named: imageName)
  // 2
  nameLabel.textColor = .systemGray2
  bioLabel.textColor = .systemGray3
  sourceLabel.textColor = .systemGray3
  // 3
  sourceLabel.font = UIFont.italicSystemFont(
    ofSize: sourceLabel.font.pointSize)
  nameLabel.textAlignment = .center
  // 4
  selectionStyle = .none
  return self
}

The code above is fairly self-explanatory. You’re simply setting the:

  1. Contents of each of the views.
  2. Label text colors to different system colors that adapt to light and dark mode.
  3. Source label to use an italicized system font.
  4. Cell selection style to none.

Open AuteurListViewController.swift. Replace tableView(_:cellForRowAt:) with:

func tableView(
  _ tableView: UITableView,
  cellForRowAt indexPath: IndexPath
) -> UITableViewCell {
  let cell = tableView.dequeueReusableCell(
    withIdentifier: "AuteurCell",
    for: indexPath
  ) as? AuteurTableViewCell ?? AuteurTableViewCell(
    style: .default, reuseIdentifier: "AuteurCell")
  let auteur = auteurs[indexPath.row]
  return cell.configure(
    name: auteur.name,
    bio: auteur.bio,
    sourceText: auteur.source,
    imageName: auteur.image)
}

This uses configure(name:bio:sourceText:imageName:) to configure the cell for display.

Build and run.

Auteurs list now has images

Not bad, but you can take it to the next level by adding expanding cells to reveal more information about films from an auteur. Your client will love this!