add additional buttons in UITableView swipe
Asked Answered
W

2

17

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.

Whereunto answered 9/1, 2015 at 6:40 Comment(0)
V
49

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]
}
Veats answered 9/1, 2015 at 8:4 Comment(5)
Thanks for your suggestion about editing titles. But in fact I was trying to do something about customizing the NSFetchedResultsController to enable additional btns. Your answer provide another solution to fix this problem but is not my original intension. Again thanks for your answer.Whereunto
Maybe you could clarify then @Whereunto I'm more than willing to edit my answer. The reason I'm confused is because the NSFetchedResultsController simply retrieves info from core data to display in UITableView. The action buttons are part of the UITableView not fetch controller. If you could post a reference link or picture to your issue I might better understand to help you outVeats
It seems I am totally wrong. I didn't realize "The action buttons are part of the UITableView not fetch controller". I thought the buttons belongs to the fetch controller. :(Whereunto
I have fixed titles. Thanks again for your generous help!Whereunto
@Whereunto it's ok. We're all here to learn and grow! I just didn't want to leave you hanging without a resolution to your problem. That's why I was suggesting you edit the title so other people with the same issue could find a solution.Veats
S
12

All kudos to @soulshined accepted answer.

Here is the Swift 3 version of it:

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    let delete = UITableViewRowAction(style: .default, title: "Delete") { (action:UITableViewRowAction, indexPath:IndexPath) in
        print("delete at:\(indexPath)")
    }
    delete.backgroundColor = .red

    let more = UITableViewRowAction(style: .default, title: "More") { (action:UITableViewRowAction, indexPath:IndexPath) in
        print("more at:\(indexPath)")
    }
    more.backgroundColor = .orange

    return [delete, more]
}
Sap answered 21/3, 2017 at 17:40 Comment(1)
Thanks for the conversion.Bitters

© 2022 - 2024 — McMap. All rights reserved.