UITableView
iOS development
Swift programming
user interface
code customization

Is there any way to hide - Delete button while editing UITableView

Interview Questions practice on Codemia

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

Browse interview questions

Introduction

When a UITableView enters editing mode, iOS shows a red minus button on each row by default, inviting the user to delete it. Sometimes you want editing mode active for reordering rows or for a custom UI, but you do not want the delete button to appear. Understanding the delegate methods that control editing style gives you precise, per-row control over which buttons appear and which stay hidden.

How UITableView Editing Mode Works

Calling tableView.setEditing(true, animated: true) puts the table into editing mode. In this state, iOS consults your data source and delegate to decide what each row should look like. The key decision is the editing style, which can be .delete (red minus), .insert (green plus), or .none (no button). If you do not implement the relevant delegate method, every row defaults to .delete.

Hiding the Delete Button with editingStyleForRowAt

The most direct way to hide the delete button is to return .none from the tableView(_:editingStyleForRowAt:) delegate method. This tells iOS that the row should not display any editing control.

swift
1func tableView(
2    _ tableView: UITableView,
3    editingStyleForRowAt indexPath: IndexPath
4) -> UITableViewCell.EditingStyle {
5    return .none
6}

With this in place, rows enter editing mode without showing the minus button. This is useful when you only need reordering handles.

Preventing Editing Entirely with canEditRowAt

If certain rows should not be editable at all, return false from tableView(_:canEditRowAt:). Unlike returning .none from the editing style method, this completely opts the row out of editing mode. The row will not indent, will not show any editing control, and will not respond to swipe-to-delete.

swift
1func tableView(
2    _ tableView: UITableView,
3    canEditRowAt indexPath: IndexPath
4) -> Bool {
5    // Only allow editing on section 1
6    return indexPath.section == 1
7}

Conditional Editing Per Row

You can combine these methods to give each row a different behavior. For example, you might want the first section to be non-editable, the second section to show insert buttons, and the third section to be reorderable with no delete button.

swift
1func tableView(
2    _ tableView: UITableView,
3    canEditRowAt indexPath: IndexPath
4) -> Bool {
5    // Section 0 is not editable at all
6    return indexPath.section != 0
7}
8
9func tableView(
10    _ tableView: UITableView,
11    editingStyleForRowAt indexPath: IndexPath
12) -> UITableViewCell.EditingStyle {
13    switch indexPath.section {
14    case 1:
15        return .insert
16    case 2:
17        return .none  // Reorder only, no delete button
18    default:
19        return .delete
20    }
21}

When returning .none, you typically also implement tableView(_:moveRowAt:to:) so the user can reorder rows even though there is no delete or insert control.

Using the Insert Style Instead of Delete

Sometimes replacing delete with insert is the right choice. Returning .insert shows a green plus button instead of the red minus. This is common in screens where users pick items from a list to add them elsewhere.

swift
1func tableView(
2    _ tableView: UITableView,
3    editingStyleForRowAt indexPath: IndexPath
4) -> UITableViewCell.EditingStyle {
5    return .insert
6}
7
8func tableView(
9    _ tableView: UITableView,
10    commit editingStyle: UITableViewCell.EditingStyle,
11    forRowAt indexPath: IndexPath
12) {
13    if editingStyle == .insert {
14        // Handle adding the item
15        addItem(at: indexPath)
16    }
17}

Customizing Swipe Actions

Starting with iOS 11, you can fully customize the trailing and leading swipe actions using trailingSwipeActionsConfigurationForRowAt and leadingSwipeActionsConfigurationForRowAt. To disable the swipe-to-delete gesture while keeping editing mode, return a configuration with no actions.

swift
1func tableView(
2    _ tableView: UITableView,
3    trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath
4) -> UISwipeActionsConfiguration? {
5    // Return an empty configuration to disable swipe-to-delete
6    return UISwipeActionsConfiguration(actions: [])
7}

You can also add custom actions like "Archive" or "Flag" instead of the default delete:

swift
1func tableView(
2    _ tableView: UITableView,
3    trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath
4) -> UISwipeActionsConfiguration? {
5    let archive = UIContextualAction(
6        style: .normal,
7        title: "Archive"
8    ) { action, view, completion in
9        self.archiveItem(at: indexPath)
10        completion(true)
11    }
12    archive.backgroundColor = .systemBlue
13    return UISwipeActionsConfiguration(actions: [archive])
14}

Preventing the Editing Indentation

Even with .none editing style, rows may still indent when entering editing mode. To prevent this, implement:

swift
1func tableView(
2    _ tableView: UITableView,
3    shouldIndentWhileEditingRowAt indexPath: IndexPath
4) -> Bool {
5    return false
6}

Common Pitfalls

  • Forgetting to implement editingStyleForRowAt and wondering why every row shows the delete button, since .delete is the default.
  • Returning .none from editingStyleForRowAt but not implementing commit editingStyle, which can still allow swipe-to-delete on older iOS versions.
  • Confusing canEditRowAt (opts out of editing entirely) with editingStyleForRowAt returning .none (enters editing mode without a button).
  • Not returning an empty UISwipeActionsConfiguration when you want to disable swipe gestures, since returning nil uses the default delete action.
  • Forgetting shouldIndentWhileEditingRowAt when you want rows to stay visually unchanged in editing mode.

Summary

  • Return .none from tableView(_:editingStyleForRowAt:) to hide the delete button while keeping the row in editing mode.
  • Return false from tableView(_:canEditRowAt:) to completely exclude a row from editing.
  • Use .insert instead of .delete when you need a green plus button for adding items.
  • Customize swipe behavior with trailingSwipeActionsConfigurationForRowAt and return an empty configuration to disable swipe-to-delete.
  • Combine these delegate methods for fine-grained, per-row control over editing behavior.

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.