Swift
UITableView
Dynamic Height
iOS Development
UITableViewCell

Dynamic Height Issue for UITableView Cells Swift

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Dynamic table cell height in Swift depends on Auto Layout constraints, row height settings, and proper reuse behavior. If any piece is missing, cells may clip content or show excessive whitespace. This guide provides a reliable setup for self-sizing UITableViewCell instances and explains how to debug common failures.

Enable Self-Sizing Table Cells

Start by configuring the table view to use automatic dimensions.

swift
1import UIKit
2
3final class MessagesViewController: UITableViewController {
4    private let rows = [
5        "Short text",
6        "A much longer text that should wrap across multiple lines and increase the cell height automatically based on Auto Layout constraints.",
7        "Another long paragraph to validate dynamic sizing in table view cells."
8    ]
9
10    override func viewDidLoad() {
11        super.viewDidLoad()
12        tableView.register(MessageCell.self, forCellReuseIdentifier: "MessageCell")
13        tableView.rowHeight = UITableView.automaticDimension
14        tableView.estimatedRowHeight = 80
15    }
16
17    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
18        rows.count
19    }
20
21    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
22        let cell = tableView.dequeueReusableCell(withIdentifier: "MessageCell", for: indexPath) as! MessageCell
23        cell.configure(text: rows[indexPath.row])
24        return cell
25    }
26}

The estimate improves scroll performance before exact heights are calculated.

Build a Constraint-Complete Cell

A self-sizing cell needs unbroken constraints from top to bottom in contentView.

swift
1import UIKit
2
3final class MessageCell: UITableViewCell {
4    private let messageLabel = UILabel()
5
6    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
7        super.init(style: style, reuseIdentifier: reuseIdentifier)
8
9        messageLabel.translatesAutoresizingMaskIntoConstraints = false
10        messageLabel.numberOfLines = 0
11        messageLabel.font = .preferredFont(forTextStyle: .body)
12
13        contentView.addSubview(messageLabel)
14
15        NSLayoutConstraint.activate([
16            messageLabel.topAnchor.constraint(equalTo: contentView.layoutMarginsGuide.topAnchor),
17            messageLabel.leadingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor),
18            messageLabel.trailingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.trailingAnchor),
19            messageLabel.bottomAnchor.constraint(equalTo: contentView.layoutMarginsGuide.bottomAnchor)
20        ])
21    }
22
23    required init?(coder: NSCoder) {
24        fatalError("init(coder:) has not been implemented")
25    }
26
27    func configure(text: String) {
28        messageLabel.text = text
29    }
30}

If any anchor is missing, Auto Layout cannot derive stable height.

Debug Sizing Problems

Use runtime diagnostics early:

  • Set a temporary background color on labels and contentView to spot clipping.
  • Run with Auto Layout warnings visible and fix ambiguous constraints first.
  • Check that multiline labels use numberOfLines = 0.

You can also force a layout pass while debugging:

swift
1override func viewDidAppear(_ animated: Bool) {
2    super.viewDidAppear(animated)
3    tableView.reloadData()
4    tableView.layoutIfNeeded()
5}

This helps surface constraint issues consistently.

Performance Considerations

Dynamic cells are powerful but can become expensive if each cell performs heavy work during configuration. Keep formatting and image decoding outside cellForRowAt when possible.

Use cached layout-independent values, and avoid repeatedly creating attributed strings for unchanged content on each reuse.

For very large lists, good estimatedRowHeight values reduce layout jitter and improve perceived performance.

Handling Asynchronous Content Updates

Dynamic heights often break after asynchronous updates, such as when images or remote text arrive after initial render. When content changes, update the model first, then reload affected rows or use batch updates so the table recalculates heights.

swift
1func updateRow(at indexPath: IndexPath, with text: String) {
2    rows[indexPath.row] = text
3    tableView.performBatchUpdates({
4        tableView.reloadRows(at: [indexPath], with: .none)
5    })
6}

For image-driven heights, provide placeholder constraints so initial layout is valid before download completes. Then trigger a controlled row refresh when final image size is known. This prevents jumpy scrolling and inconsistent cell frames.

Common Pitfalls

A common issue is combining automatic row height with a fixed heightForRowAt implementation. The fixed delegate return overrides self-sizing.

Another pitfall is forgetting to pin bottom anchors inside the cell. Missing bottom constraints are a primary cause of zero or incorrect height.

Developers also leave labels at single-line default configuration. Text then truncates instead of expanding the cell.

A final issue is reusing cells with stale content-related properties. Always reset view state in prepareForReuse when needed.

Summary

  • Enable automaticDimension and provide a realistic estimated row height.
  • Ensure cell constraints form a complete top-to-bottom chain.
  • Use multiline labels for variable text content.
  • Debug with Auto Layout warnings and visual background checks.
  • Keep configuration lightweight to preserve smooth scrolling.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.