Making table cells reorderable

by @ralfebert · updated February 05, 2019

This example shows how to make UITableView cells reorderable:

Reorderable/Movable table cells
  1. Download as a starting point. This contains a simple UITableViewController with regular cells. Make yourself familiar with the code. If it is not straightforward to you, have a look at the UITableViewController tutorial.

  2. In StoriesTableViewController, overwrite the UIViewController method viewDidLoad and enable the editing mode for the UITableView:

    override func viewDidLoad() {
        self.tableView.isEditing = true
  3. Enabling the edit mode causes delete buttons to be visible for all cells:

    Delete Buttons

    Disable the buttons by implementing these UITableViewDataSource methods:

    override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
        return .none
    override func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
        return false
  4. Enable the reorder control to move cells by overwriting tableView:moveRowAtIndexPath: and implement the method so that the elements in the underlying data list are updated:

    override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        let movedObject = self.headlines[sourceIndexPath.row]
        headlines.remove(at: sourceIndexPath.row)
        headlines.insert(movedObject, at: destinationIndexPath.row)

    Hint: The table view is not reloaded after the move operation - UITableView trusts you to change the underlying model list accordingly. If you have a bug in your implementation, the UI will show the moved cell as moved by the user, but the underlying data object will have a different order.

    Hint: Many examples advise setting cell.showsReorderControl. This is not necessary, the control is automatically shown when you implement tableView:moveRowAtIndexPath:. Optionally you can overwrite canMoveRowAtIndexPath to enable the reorder control only for some rows.

  5. Run the app with ⌘R:

    Table move