iOS
UITableView
cell deselection
Swift programming
iPhone development

How to deselect a selected UITableView cell?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In UITableView, selection is a visual state, not just an event. If you push another screen after tapping a row, the usual iOS behavior is to deselect that row when the table view becomes visible again so the highlight does not remain stuck on screen.

Deselect It Immediately After Handling the Tap

If you want the row to flash selection and then clear right away, call deselectRow(at:animated:) inside tableView(_:didSelectRowAt:):

swift
1import UIKit
2
3final class ItemsViewController: UITableViewController {
4    let items = ["One", "Two", "Three"]
5
6    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
7        items.count
8    }
9
10    override func tableView(
11        _ tableView: UITableView,
12        cellForRowAt indexPath: IndexPath
13    ) -> UITableViewCell {
14        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
15            ?? UITableViewCell(style: .default, reuseIdentifier: "Cell")
16        cell.textLabel?.text = items[indexPath.row]
17        return cell
18    }
19
20    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
21        print("Selected", items[indexPath.row])
22        tableView.deselectRow(at: indexPath, animated: true)
23    }
24}

This is the simplest answer when the tap triggers work inside the same controller and you do not want the selection to persist.

Deselect It When Returning from a Pushed Screen

If tapping a row pushes a detail screen, deselecting immediately may feel abrupt because the user never sees the standard selection transition during navigation. The common iOS pattern is to deselect in viewWillAppear when the list screen becomes visible again:

swift
1override func viewWillAppear(_ animated: Bool) {
2    super.viewWillAppear(animated)
3
4    if let indexPath = tableView.indexPathForSelectedRow {
5        tableView.deselectRow(at: indexPath, animated: true)
6    }
7}

This matches the behavior of many built-in iOS apps. The row stays highlighted while the detail screen is on top, then smoothly deselects when the user navigates back.

Choose Based on UX, Not Habit

There are valid cases where you should keep the selection. For example, in a split view on iPad, the selected row may represent the current detail panel and should remain highlighted. In that layout, automatic deselection can be the wrong behavior.

A practical rule is:

  • deselect immediately for tap actions
  • deselect on return for push navigation
  • keep selection when it indicates current context

That is a better guideline than always deselecting everywhere.

Programmatic Selection and Deselecting

If you select rows in code, you can clear them the same way:

swift
let indexPath = IndexPath(row: 0, section: 0)
tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
tableView.deselectRow(at: indexPath, animated: true)

This is useful in flows where the controller restores state or highlights a row briefly after loading.

Avoid Fighting Table View State

If your row shows a checkmark or other durable selection marker, do not rely on the highlight state to represent that choice. The temporary blue or gray selection highlight is meant for interaction feedback, while a long-lived choice should be stored in your model and rendered explicitly in the cell configuration.

Common Pitfalls

  • Deselecting in the wrong lifecycle method. For pushed detail flows, viewWillAppear often feels better than immediate deselection.
  • Forgetting that persistent selection can be intentional in split view or sidebar-style interfaces.
  • Trying to clear selection by reloading the table view. deselectRow is simpler and avoids unnecessary UI work.
  • Calling deselectRow with the wrong index path after the data source has changed.
  • Assuming selection state and checked-state UI are the same thing. If you want a durable chosen item, use an accessory or custom state, not temporary row highlight alone.

Summary

  • Use tableView.deselectRow(at:animated:) to clear selection.
  • Deselect inside didSelectRowAt for immediate tap handling.
  • Deselect in viewWillAppear when returning from pushed detail screens.
  • Keep selection when it represents persistent context, such as split view state.
  • Treat selection highlight as a UX decision, not just a technical cleanup step.

Course illustration
Course illustration

All Rights Reserved.