UITableView
iOS Development
Swift
UITableViewCell
iOS UIKit

How can I disable the UITableView selection?

Master System Design with Codemia

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

Introduction

Disabling selection in a UITableView can mean a few different things. Sometimes you want rows to be completely non-selectable, sometimes you want to keep tap handling but remove the gray highlight, and sometimes only specific rows should ignore taps. UIKit supports all three cases, but they use different APIs.

Disable selection for the whole table

If no row in the table should ever become selected, set allowsSelection to false.

swift
1import UIKit
2
3final class ViewController: UIViewController {
4    @IBOutlet private weak var tableView: UITableView!
5
6    override func viewDidLoad() {
7        super.viewDidLoad()
8        tableView.allowsSelection = false
9    }
10}

This is the cleanest option for read-only tables. If allowsSelection is false, didSelectRowAt will not be called for normal row taps.

There is a related property called allowsSelectionDuringEditing. Use that separately if the table enters editing mode and your selection rules change there.

Remove the highlight but keep the row interactive

Sometimes the row still performs an action, but you do not want the default selected appearance. In that case, do not disable table selection globally. Instead, change the cell's selection style.

swift
1func tableView(
2    _ tableView: UITableView,
3    cellForRowAt indexPath: IndexPath
4) -> UITableViewCell {
5    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
6    cell.selectionStyle = .none
7    cell.textLabel?.text = "Row \(indexPath.row)"
8    return cell
9}
10
11func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
12    print("Tapped row \(indexPath.row)")
13}

This is a very common point of confusion: selectionStyle = .none changes appearance, not behavior. The row can still be selected and your delegate method can still run.

Disable selection only for certain rows

If some rows should respond to taps and others should not, implement willSelectRowAt and return nil for the rows you want to block.

swift
1func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
2    if indexPath.section == 0 {
3        return nil
4    }
5    return indexPath
6}

That gives row-level control without changing the rest of the table. It is usually a better fit than toggling allowsSelection on and off as the user scrolls.

You can combine this with selectionStyle = .none so blocked rows also look non-interactive.

Keep the UX consistent

The technical property is easy. The harder part is making the interface communicate the right affordance.

If a row does nothing, it should generally not look tappable. If a row still navigates somewhere or reveals details, removing every visual cue can make the table feel broken. In many cases, the better solution is to keep selection and simply deselect the row after the action:

swift
1func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
2    tableView.deselectRow(at: indexPath, animated: true)
3    print("Navigate to detail screen")
4}

That preserves the standard iOS interaction pattern while avoiding a row that stays highlighted.

Also remember that cells can contain controls such as switches, buttons, and steppers. Disabling row selection does not automatically disable those controls, which is often exactly what you want in settings-style screens.

Common Pitfalls

The most common mistake is setting selectionStyle = .none and assuming row selection itself is disabled. It is not.

Another mistake is disabling allowsSelection globally when only a few rows should ignore taps. That usually removes useful behavior from the rest of the screen.

People also forget about editing mode. A table that should not allow normal selection may still need allowsSelectionDuringEditing configured explicitly.

Finally, removing the highlight without replacing it with any other visual cue can make interactive rows feel dead even though they still work.

Summary

  • Use tableView.allowsSelection = false to disable row selection entirely.
  • Use cell.selectionStyle = .none when you only want to remove the highlight.
  • Return nil from willSelectRowAt for row-specific control.
  • Call deselectRow if you want standard tap behavior without a lingering highlight.
  • Match the visual affordance of each row to what it actually does.

Course illustration
Course illustration

All Rights Reserved.