UITableView Custom Edit Button In Each Row With Swift

This post will illustrate how to have a custom Edit button next to the UIKit Delete icon when a UITableView is in Edit mode. By Edit, I don’t mean the green plus sign to add an entry. This Edit button is for editing data in the row.

Here are screenshots of what the rows will look like when in normal and Edit mode.



26 Feb 2017: I’ve updated the code in GitHub to be Swift 3 compliant.

Note: I’ve experimented with editActionsForRowAtIndexPath, and this permits an Edit and Delete button to be added on the right hand side, but there are two main reasons why I’ve taken a different approach:

  • It requires a swipe, and I still prefer the Edit button in the navigation bar.
  • Handling of the row contents isn’t optimal, as it slides over and is cut off.

The first thing I did for this example was build my own Edit icon in Sketch 3. Feel free to use the icon if it helps in your own project. If you want the Sketch file, let me know.

The example is working with Swift books, where each Book has a Title and Author.

In the storyboard, there is a DataView and ButtonView defined within the single Prototype cell that has an identifier of bookCell. In the screenshot below, I’ve expanded the outline to show all the constraints. By default (when not in Edit mode) the Button Width constraint of the Edit button is 0. This will change when in edit mode and the ButtonView will be visible in Edit mode, and hidden normally. We need the width constraint of 0 in normal mode otherwise the button takes up space in the cell.

Screen Shot 2015-10-29 at 7.04.30 AM

The rest of the constraints are fairly standard. The Book Title should be left justified and on top, while the Author is right justified and below the Book Title.

There is an implementation of UITableViewCell for the bookCell. This class is BookTableViewCell and it has the IBOutlet definitions we need in order to work with the dynamic cell.

The rest of the code is in TableWithEditIconsController. We want each row to be automatically sized based on the content, as you can see in viewDidLoad with the UITableViewAutomaticDimension.

We’ve also set the rightBarButtonItem via self.editButtonItem(), which is how we enter Edit mode.

In the cellForRowAtIndexPath, the cell is configured depending on whether the table should be normal or Edit mode. In Edit mode, the buttonView is visible with a width constraint in proportion to the cell width, versus hidden with a width constraint of 0 when in normal mode.

The other methods to discuss are as shown below.

In this example, canEditRowAtIndexPath always returns true, so all rows are editable. If some items in the data source were not editable, that method would return false for the corresponding row based on the data it contained.

In commitEditingStyle, a Delete is handled by removing an item and reloading the table. Finally, the setEditing method is how the Edit button is shown in each row when the table enters Edit mode, since it triggers a reloadData, and the logic to display the button is in cellForRowAtIndexPath.

There are a couple of other things to note. When you click the Edit button in a row, for this example I’ve just implemented a placeholder controller where the editing would be done. Also, using this method of editing versus the swipe results in the cell content resizing once the Edit and Delete buttons are present, which I like.

The code for this tutorial is in Github.

Update May 19, 2016: If you are targeting iOS 9.0 or higher, you can design the interface using UIStackView, which eliminates all constraints other than those required for the top level UIStackView. It also facilitates using one of the nice features of UIStackView, which is showing and hiding views. I’ve put up a new tutorial to illustrate this using the same custom edit button functionality. You can find that tutorial here on my website.

Leave a Comment: