iOS

Making table cells reorderable

Today let us discuss how to make UITableView cells reorderable:

table_move_animation

 

Use your TableExample project from the introductory UITableViewController tutorial or download TableExample.zip as a starting point.

 

In FruitsTableViewController, overwrite the UIViewController method viewDidLoad and enable the editing mode for the UITableView:

 

override func viewDidLoad() {
    super.viewDidLoad()
    self.tableView.isEditing = true
}

 

Alternatively, you can add an Edit button as Right Bar Button Item:

To enable this, set the rightBarButtonItem to the editButtonItem of the Table View Controller instead of enabling the editing mode immediately:

self.navigationItem.rightBarButtonItem = self.editButtonItem

 

Enabling the edit mode causes delete buttons to be visible for all cells:screen_delete_buttons

 

Disable the buttons by implementing these UITableViewDataSource methods:

 

override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
    return .none
}

override func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
    return false
}

 

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.fruits[sourceIndexPath.row]
    fruits.remove(at: sourceIndexPath.row)
    fruits.insert(movedObject, at: destinationIndexPath.row)
    NSLog("%@", "\(sourceIndexPath.row) => \(destinationIndexPath.row) \(fruits)")
    // To check for correctness enable: self.tableView.reloadData()
}

 

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 data object will have a different order. To check for the correctness of your implementation, use NSLog or reload the table after the move operation.

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:

override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
    let rowData = fruits[indexPath.row]
    return rowData.hasPrefix("A")
}

Run the app with ⌘R:

table_move_animation1

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s