add additional buttons in UITableView swipe

AlexWei picture AlexWei · Jan 9, 2015 · Viewed 15.2k times · Source

Currently I am using NSFetchedResultsController to handle tableviews. I am wondering is there any way to add additional buttons like the delete button in swipe operation?

I am thinking about to subclass it. But find nothing relevant in help docs to my problems.

Thanks in advance.

Answer

soulshined picture soulshined · Jan 9, 2015

Your title is misleading. NSFetchedResultsController has no relevance to your end goal. Subclassing would just create more work than necessary, what you want to look into is UITableViewRowAction. This handles very easily & similarly to the new UIAlertController, so you should feel extremely comfortable with this if you've already dabbled with the UIAlertController

A brief synopsis (straight from the docs) of UITableViewRowAction:

Asks the delegate for the actions to display in response to a swipe in the specified row. (required) Use this method when you want to provide custom actions for one of your table rows. When the user swipes horizontally in a row, the table view moves the row content aside to reveal your actions. Tapping one of the action buttons executes the handler block stored with the action object. If you do not implement this method, the table view displays the standard accessory buttons when the user swipes the row.

A couple notes before you begin :

  • Apple implemented this in iOS8 : so think carefully about your deployment target. If you are coding strictly for i0S8 this is a quick and easy alternative to 3rd party libraries or creating a custom UITableView editing style. If you aim to retain compatibility for iOS7 your options are limited with this format. SIDE NOTE this does not cause a fatal error in your code, iOS7 apps will not crash, however, the custom actions simply won't display.
  • There is not much customizing beyond the title
  • The pros of this, is that everything is handled with blocks

Regardless, to implement a custom UITableViewRowAction you must first ensure your table is editable by calling the following methods:

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    //Obviously, if this returns no, the edit option won't even populate
    return YES;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    //Nothing gets called here if you invoke `tableView:editActionsForRowAtIndexPath:` according to Apple docs so just leave this method blank
}

At minimum, those are the two methods that need to be declared before moving on.

To actually customize your row action buttons, follow the general guideline as follows:

STEP 1 implement the tableView:editActionsForRowAtIndexPath: method

-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
}

As you can see, it's an instance method of type NSArray, so you have to return an array.

STEP 2 Add action objects to pass in the array. An example:

{

UITableViewRowAction *delete = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Delete" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
{
    // Delete something here
}];

UITableViewRowAction *more = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@" More " handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
{
    //Do whatever here : just as an example :
    [self presentUIAlertControllerActionSheet];
}];

}    

You can alter a few properties for these row actions, but see the documents for complete customization options:

To customize the row action background colors, simply preform it like most other actions within buttons:

delete.backgroundColor = [UIColor redColor];
more.backgroundColor = [UIColor colorWithRed:0.188 green:0.514 blue:0.984 alpha:1]; //arbitrary color

STEP 3 As mentioned before you have to return an array in the instance method so your complete code should resemble the following :

-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewRowAction *delete = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Delete" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
    {
        // Delete something here
    }];
    delete.backgroundColor = [UIColor redColor];

    UITableViewRowAction *more = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@" More " handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
    {
        //Just as an example :
        [self presentUIAlertControllerActionSheet];
    }];
    more.backgroundColor = [UIColor colorWithRed:0.188 green:0.514 blue:0.984 alpha:1];

    return @[delete, more]; //array with all the buttons you want. 1,2,3, etc...
}    

For further reference : LINK TO DOCUMENTATION


EDITED FOR SWIFT SYNTAX

override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]?  {

var delete = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Delete" , handler: { (action:UITableViewRowAction!, indexPath:NSIndexPath!) -> Void in
    //Do something
})
delete.backgroundColor = UIColor.redColor()

var more = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "More" , handler: { (action:UITableViewRowAction!, indexPath:NSIndexPath!) -> Void in
    //Do something
})
more.backgroundColor = UIColor.blueColor()

    return [delete, more]
}