Add swipe to delete UITableViewCell
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Swipe-to-delete is one of the most recognizable gestures in iOS. Users expect it in any list-based interface, from email inboxes to to-do apps. UITableView has built-in support for this interaction, and understanding how it works — from the basic delegate method to fully customized swipe actions — will help you build polished, intuitive table views.
Basic Swipe-to-Delete with commit editingStyle
The simplest way to enable swipe-to-delete is to implement a single UITableViewDataSource method. When you provide this method, UITableView automatically adds a red "Delete" button that appears when the user swipes left on a cell:
The critical detail here is the order of operations: you must update your data source first, then call deleteRows(at:with:). If the data source count does not match the expected count after the deletion, your app will crash with an internal consistency exception.
Custom Trailing Swipe Actions
For anything beyond a plain delete button, use trailingSwipeActionsConfigurationForRowAt. This delegate method lets you define multiple actions with custom titles, colors, and images:
The style: .destructive parameter is important because it tells UIKit this action removes the cell. UIKit uses this information to animate the cell removal correctly. Non-destructive actions use style: .normal and keep the cell visible after the action completes.
Leading Swipe Actions
You can also add actions that appear when the user swipes from left to right. This is useful for positive actions like marking items as favorites or marking messages as read:
Destructive vs Non-Destructive Actions
The distinction between destructive and non-destructive actions affects both appearance and behavior:
When you call completionHandler(true) on a destructive action, UIKit animates the cell off screen. Calling completionHandler(false) indicates the action failed and the cell slides back to its original position.
Updating the Data Source Safely
The most crash-prone part of swipe-to-delete is keeping the data source in sync with the table view. Always wrap multiple changes in performBatchUpdates to avoid inconsistency crashes:
If you are using a UITableViewDiffableDataSource (iOS 13+), the snapshot-based approach eliminates these index management issues entirely:
Common Pitfalls
- Updating the table view before the data source: Always remove the item from your array or database first, then call
deleteRows(at:with:)— reversing this order causes a crash. - Forgetting to call the completion handler: Every
UIContextualActionhandler receives acompletionHandlerclosure that you must call, or the swipe UI will freeze in place. - Not using
[weak self]in action closures: The closure capturesselfstrongly by default, which can create retain cycles with the view controller. - Allowing full swipe on dangerous actions: Set
performsFirstActionWithFullSwipe = falseon the configuration to prevent accidental deletions from a fast swipe gesture. - Ignoring accessibility: Swipe actions are not discoverable by VoiceOver users by default — implement
accessibilityCustomActionson your cells so all users can access these features.
Summary
- Implement
tableView(_:commit:forRowAt:)for basic swipe-to-delete with minimal code. - Use
trailingSwipeActionsConfigurationForRowAtandleadingSwipeActionsConfigurationForRowAtfor custom swipe actions with colors, images, and multiple buttons. - Set
style: .destructivefor actions that remove the cell andstyle: .normalfor actions that keep it visible. - Always update your data source before telling the table view to delete rows to avoid internal consistency crashes.
- Use
performsFirstActionWithFullSwipe = falseto prevent accidental full-swipe deletions on destructive actions.

