An easy-to-use UITableViewCell subclass that implements a swippable content view which exposes utility buttons (similar to iOS 7 Mail Application)

Last update: Jul 27, 2022

SWTableViewCell

Build Status Coverage Status

An easy-to-use UITableViewCell subclass that implements a swipeable content view which exposes utility buttons (similar to iOS 7 Mail Application)

##Usage In your Podfile:

pod 'SWTableViewCell', '~> 0.3.7'

Or just clone this repo and manually add source to project

##Functionality ###Right Utility Buttons Utility buttons that become visible on the right side of the Table View Cell when the user swipes left. This behavior is similar to that seen in the iOS apps Mail and Reminders.

###Left Utility Buttons Utility buttons that become visible on the left side of the Table View Cell when the user swipes right.

###Features

  • Dynamic utility button scalling. As you add more buttons to a cell, the other buttons on that side get smaller to make room
  • Smart selection: The cell will pick up touch events and either scroll the cell back to center or fire the delegate method - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

So the cell will not be considered selected when the user touches the cell while utility buttons are visible, instead the cell will slide back into place (same as iOS 7 Mail App functionality) * Create utilty buttons with either a title or an icon along with a RGB color * Tested on iOS 6.1 and above, including iOS 7

##Usage

###Standard Table View Cells

In your tableView:cellForRowAtIndexPath: method you set up the SWTableView cell and add an arbitrary amount of utility buttons to it using the included NSMutableArray+SWUtilityButtons category.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *cellIdentifier = @"Cell";
    
    SWTableViewCell *cell = (SWTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    
    if (cell == nil) {
        cell = [[SWTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
        cell.leftUtilityButtons = [self leftButtons];
        cell.rightUtilityButtons = [self rightButtons];
        cell.delegate = self;
    }
    
    NSDate *dateObject = _testArray[indexPath.row];
    cell.textLabel.text = [dateObject description];
    cell.detailTextLabel.text = @"Some detail text";
    
    return cell;
}

- (NSArray *)rightButtons
{
    NSMutableArray *rightUtilityButtons = [NSMutableArray new];
    [rightUtilityButtons sw_addUtilityButtonWithColor:
     [UIColor colorWithRed:0.78f green:0.78f blue:0.8f alpha:1.0]
                                                title:@"More"];
    [rightUtilityButtons sw_addUtilityButtonWithColor:
     [UIColor colorWithRed:1.0f green:0.231f blue:0.188 alpha:1.0f]
                                                title:@"Delete"];

    return rightUtilityButtons;
}

- (NSArray *)leftButtons
{
    NSMutableArray *leftUtilityButtons = [NSMutableArray new];
    
    [leftUtilityButtons sw_addUtilityButtonWithColor:
     [UIColor colorWithRed:0.07 green:0.75f blue:0.16f alpha:1.0]
                                                icon:[UIImage imageNamed:@"check.png"]];
    [leftUtilityButtons sw_addUtilityButtonWithColor:
     [UIColor colorWithRed:1.0f green:1.0f blue:0.35f alpha:1.0]
                                                icon:[UIImage imageNamed:@"clock.png"]];
    [leftUtilityButtons sw_addUtilityButtonWithColor:
     [UIColor colorWithRed:1.0f green:0.231f blue:0.188f alpha:1.0]
                                                icon:[UIImage imageNamed:@"cross.png"]];
    [leftUtilityButtons sw_addUtilityButtonWithColor:
     [UIColor colorWithRed:0.55f green:0.27f blue:0.07f alpha:1.0]
                                                icon:[UIImage imageNamed:@"list.png"]];
    
    return leftUtilityButtons;
}

###Custom Table View Cells

Thanks to Matt Bowman you can now create custom table view cells using Interface Builder that have the capabilities of an SWTableViewCell

The first step is to design your cell either in a standalone nib or inside of a table view using prototype cells. Make sure to set the custom class on the cell in interface builder to the subclass you made for it:

Then set the cell reuse identifier:

When writing your custom table view cell's code, make sure your cell is a subclass of SWTableViewCell:

#import <SWTableViewCell.h>

@interface MyCustomTableViewCell : SWTableViewCell

@property (weak, nonatomic) UILabel *customLabel;
@property (weak, nonatomic) UIImageView *customImageView;

@end

If you are using a separate nib and not a prototype cell, you'll need to be sure to register the nib in your table view:

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self.tableView registerNib:[UINib nibWithNibName:@"MyCustomTableViewCellNibFileName" bundle:nil] forCellReuseIdentifier:@"MyCustomCell"];
}

Then, in the tableView:cellForRowAtIndexPath: method of your UITableViewDataSource (usually your view controller), initialize your custom cell:

- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
    static NSString *cellIdentifier = @"MyCustomCell";
    
    MyCustomTableViewCell *cell = (MyCustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier 
                                                                                           forIndexPath:indexPath];

    cell.leftUtilityButtons = [self leftButtons];
    cell.rightUtilityButtons = [self rightButtons];
    cell.delegate = self;
    
    cell.customLabel.text = @"Some Text";
    cell.customImageView.image = [UIImage imageNamed:@"MyAwesomeTableCellImage"];
    [cell setCellHeight:cell.frame.size.height];
    return cell;
}

###Delegate

The delegate SWTableViewCellDelegate is used by the developer to find out which button was pressed. There are five methods:

// click event on left utility button
- (void)swipeableTableViewCell:(SWTableViewCell *)cell didTriggerLeftUtilityButtonWithIndex:(NSInteger)index;

// click event on right utility button
- (void)swipeableTableViewCell:(SWTableViewCell *)cell didTriggerRightUtilityButtonWithIndex:(NSInteger)index;

// utility button open/close event
- (void)swipeableTableViewCell:(SWTableViewCell *)cell scrollingToState:(SWCellState)state;

// prevent multiple cells from showing utilty buttons simultaneously
- (BOOL)swipeableTableViewCellShouldHideUtilityButtonsOnSwipe:(SWTableViewCell *)cell;

// prevent cell(s) from displaying left/right utility buttons
- (BOOL)swipeableTableViewCell:(SWTableViewCell *)cell canSwipeToState:(SWCellState)state;

The index signifies which utility button the user pressed, for each side the button indices are ordered from right to left 0...n

####Example

#pragma mark - SWTableViewDelegate

- (void)swipeableTableViewCell:(SWTableViewCell *)cell didTriggerLeftUtilityButtonWithIndex:(NSInteger)index {
    switch (index) {
        case 0:
            NSLog(@"check button was pressed");
            break;
        case 1:
            NSLog(@"clock button was pressed");
            break;
        case 2:
            NSLog(@"cross button was pressed");
            break;
        case 3:
            NSLog(@"list button was pressed");
        default:
            break;
    }
}

- (void)swipeableTableViewCell:(SWTableViewCell *)cell didTriggerRightUtilityButtonWithIndex:(NSInteger)index {
    switch (index) {
        case 0:
            NSLog(@"More button was pressed");
            break;
        case 1:
        {
            // Delete button was pressed
            NSIndexPath *cellIndexPath = [self.tableView indexPathForCell:cell];
            
            [_testArray removeObjectAtIndex:cellIndexPath.row];
            [self.tableView deleteRowsAtIndexPaths:@[cellIndexPath] 
                    withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        }
        default:
            break;
    }
}

(This is all code from the included example project)

###Gotchas

Seperator Insets

  • If you have left utility button on iOS 7, I recommend changing your Table View's seperatorInset so the seperator stretches the length of the screen
 tableView.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0); 

##Contributing Use Github issues to track bugs and feature requests.

##Contact

Chris Wendel

Licence

MIT

GitHub

https://github.com/CEWendel/SWTableViewCell
Comments
  • 1. Crash in iOS6.1

    I run this demo project on my iOS6.1 simulator. But got crashed with information belows:

    2014-04-24 23:39:19.772 SWTableViewCell[17539:907] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. SWTableViewCell's implementation of -layoutSubviews needs to call super.'

    Any one occurs?

    Reviewed by wdragen at 2014-04-24 15:46
  • 2. The view hierarchy is not prepared for the constraint

    I have subclassed SWTableViewCell and registered my nib w/ the tableview. When I run the application however I get the following the debug console

    2015-03-24 21:58:42.852 ohio[18231:343586] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7fbed35b0890 SWUtilityButtonView:0x7fbed35afaa0.width <= UITableViewCellContentView:0x7fbed35acff0.width - 90>
        When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.
    2015-03-24 21:58:42.852 ohio[18231:343586] *** Assertion failure in -[ohio.ConnectionsTableViewCell _layoutEngine_didAddLayoutConstraint:roundingAdjustment:mutuallyExclusiveConstraints:], /SourceCache/UIKit_Sim/UIKit-3347.16.1/NSLayoutConstraint_UIKitAdditions.m:560
    

    The application doesn't crash but I don't see my cells. I'm using cocoapods and pulling from the github repo.

    Reviewed by kyledecot at 2015-03-25 02:01
  • 3. Adjust library to allow for the use of custom views built in interface builder

    This change does a few things:

    1. Breaks apart the classes to make it easier to navigate
    2. Update the cocoa pod spec to use the new location for the library files
    3. Allows the user to set the table view, left buttons and right buttons after initialization
    4. Allow the use of custom views built in interface builder
    Reviewed by MattCBowman at 2013-11-27 20:23
  • 4. use existing delegate method to close open cells on table swipe

    When a pan begins on the tableview, all open cells (except for the one being touched/panned) will call the swipeableTableViewCellShouldHideUtilityButtonsOnSwipe: delegate method and close if YES.

    This is pretty much exactly how the Mail.app tables behaves and seems like something that should be included in the core.

    Reviewed by DimaVartanian at 2014-04-27 22:10
  • 5. Right utility buttons don't work properly on iOS 8

    On iOS 8, the right utility buttons don't seem to be working properly. Using the sample project with a minor change, setting useCustomCells to YES in viewDidLoad, the left utility buttons opens correctly but the right utility buttons do not.

    Here's a little movie of me doing this: https://dl.dropboxusercontent.com/u/30096/SWTableViewCell_iOS8_with_left_buttons.mov

    Interestingly, after I tap and hold on the cell, swiping to show the right buttons work again.

    If I disable the left buttons, the swiping doesn't work at all until I tap and hold.

    https://dl.dropboxusercontent.com/u/30096/SWTableViewCell_iOS8_without_left_buttons.mov

    This only happens on iOS 8 and not iOS 7.

    Reviewed by hongrich at 2014-09-11 20:55
  • 6. Buttons disappears after touching the cell

    Hi, I imported the latest fixes and noticed an issue. When I click on a cell when buttons are hidden, when I try to swipe, blank area shows up, buttons are missing. Does anyone have idea what's wrong?

    Reviewed by muchabartek at 2014-03-28 09:38
  • 7. Custom cells?

    I tried using this with a custom storyboard table prototype cell. But as I change the parent from UITableViewCell to SWTableViewCell, the cell is rendered as a blank cell.

    Does it work with custom cells or only basic?

    Reviewed by jpaas at 2013-10-08 18:09
  • 8. Only Swipe Gesture will work

    Great job. Its exactly what I was looking for. But if I implement this cell, I can only have right swipe or left swipe. Selecting a row gesture will not work. Can you improve this so that other gesture like selecting the cell?

    Reviewed by Soumin at 2013-10-08 00:12
  • 9. Buttons don't appear on iOS8 cell

    This is kind of weird, but basically the buttons don't appear until the cell is swiped on in landscape orientation and then rotated to portrait orientation.

    Using the new UIView feature of Xcode 6, I can see that the content is supposed to be there, but it really is not showing on-device.

    screen shot 2014-08-20 at 12 04 11 am

    img_4698

    Reviewed by skumancer at 2014-08-20 07:08
  • 10. No Swipe Animation or View Even though Delegate Fires

    It appears in debugging that SWTableViewCell is doing what it's meant to do from the perspective of getting to the point of firing the delegate methods. However, for some reason, it's not doing anything on my cell.

    Touch and drag does nothing until I release, and then all it does is call the "scrollingToState" delegate method. I figured this would be called with each gesture location update--IOW many times while I drag. Once done dragging, still nothing happens.

    So, the delegate gets called but nothing happens.

    Any thoughts as to why?

    I've been at this for 2 days now and about ready to give up. Any help is greatly appreciated. I really would like to use this control, but just am out of ideas.

    Reviewed by thephatp at 2014-07-09 04:03
  • 11. Buggy when combining SW and TableView editing delegate methods

    When I'm using just SWTableViewCell, everything works perfectly.

    However, when combining it with native UITableViewCell delegate methods for editing functionality, such as tableView:commitEditingStyle:forRowAtIndexPath or tableView:canMoveRowAtIndexPath:, it gets glitchy sometimes.

    I'm not doing anything out of the ordinary: tableView:cellForRowAtIndexPath: is setting rightUtilityButtons then the delegate, per the SW sample app. The tableView delegate methods are also pretty straight forward, they simply allow reordering, and deleting. I don't really care about deleting via the tableView delegate since I'm handling that in SW, but I need reordering and delete comes free with that when in edit mode.

    It looks like adding this resolves the problem. It would be nice if this "fix" wasn't necessary.

    • (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { return UITableViewCellEditingStyleNone; }

    Here's what I'm seeing happen: https://www.dropbox.com/s/rw0m5469m2nelrb/SWTableViewCell.mov

    Reviewed by jeffhatz at 2014-05-26 05:44
  • 12. iOS 15.0 Crash

    iOS 15.0 make a crash on
    "[super layoutSubviews]", when calling tableView.reloadData() or view.layoutIfNeeded()

    methid: - (void)layoutSubviews File : SWTableViewCell.m

    Reviewed by MuhammadMazhar313 at 2021-09-23 07:58
  • 13. [cell hideUtilityButtonsAnimated:YES]; 传YES不起作用

    iOS 14 [cell hideUtilityButtonsAnimated:YES]; 传yes不起作用,是因为 [self.cellScrollView setContentOffset:[self contentOffsetForCellState:kCellStateCenter] animated:animated]; 执行动画无效 这个怎么解决?

    Reviewed by guoyutao at 2020-10-30 03:42
  • 14. Drop iOS 7 support not to crush in iOS 14

    My app suddenly crushed when I built it with Xcode 12.0 beta 6 and run in iOS 14 beta 8. I found that self.subviews returns 0 during cell initialization for iOS 14. The code was for supporting iOS 7 but it's reasonable to drop it. After this change, the crush seems no longer appear.

    Reviewed by imaizume at 2020-09-11 12:18
  • 15. Sample code for show just one menu in tableview

    If you want to just show a single swipe menu in TableView can try with my sample:

    Create a property the keep last cell has shown the menu.

    @interface MyViewController ()<UITableViewDelegate,UITableViewDataSource ,SWTableViewCellDelegate>
    
    @property (nonatomic, strong) SWTableViewCell *lastSWCell;
    
    @end
    

    Then implement this code to hide the menu of the last cell has been shown.

    -(void) swipeableTableViewCell:(SWTableViewCell *)cell scrollingToState:(SWCellState)state{
        if (state != kCellStateCenter) {
            if (self.lastSWCell) {
                [self.lastSWCell hideUtilityButtonsAnimated:YES];
            }
            self.lastSWCell = cell;
        }
    }
    

    If you want to hide the menu when user scrolled the TableView implement this:

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView{
        if (self.lastSWCell) {
            [self.lastSWCell hideUtilityButtonsAnimated:YES];
            self.lastSWCell = nil;
        }
    }
    

    SampleVideo

    Reviewed by Husseinhj at 2019-01-16 07:43
An easy to use UITableViewCell subclass that allows to display swippable buttons with a variety of transitions.
An easy to use UITableViewCell subclass that allows to display swippable buttons with a variety of transitions.

MGSwipeTableCell MGSwipeTableCell is an easy to use UITableViewCell subclass that allows to display swipeable buttons with a variety of transitions. T

Aug 1, 2022
Swipeable UITableViewCell/UICollectionViewCell based on the stock Mail.app, implemented in Swift.
Swipeable UITableViewCell/UICollectionViewCell based on the stock Mail.app, implemented in Swift.

SwipeCellKit Swipeable UITableViewCell/UICollectionViewCell based on the stock Mail.app, implemented in Swift. About A swipeable UITableViewCell or UI

Aug 7, 2022
Simple timeline view implemented by UITableViewCell
Simple timeline view implemented by UITableViewCell

TimelineTableViewCell TimelineTableViewCell is a simple timeline view implemented by UITableViewCell. The UI design of TimelineTableViewCell is inspir

Aug 1, 2022
A subclass of UITableView that styles it like Settings.app on iPad
A subclass of UITableView that styles it like Settings.app on iPad

TORoundedTableView As of iOS 13, Apple has released an official version of this table view style called UITableViewStyleInsetGrouped! Yay! In order to

Mar 12, 2022
UIViewController subclass inspired by "Inbox by google" animated transitioning.
UIViewController subclass inspired by

SAInboxViewController SAInboxViewController realizes Inbox like view transitioning. You can launch sample project on web browser from here. Features I

Jun 29, 2022
This framework allows you to build Table views using UIKit with syntax similar to SwiftUI
This framework allows you to build Table views using UIKit with syntax similar to SwiftUI

This framework allows you to build Table views using UIKit with syntax similar to SwiftUI

Jul 3, 2022
Use Yelp API to fetch restuarants around a location and show them in a table view
Use Yelp API to fetch restuarants around a location and show them in a table view

Yelp Use Yelp API to fetch restuarants around a location and show them in a table view - Infinite scrolling, Prefetching, Image Caching. Design Patter

Nov 1, 2021
A PageView, which supporting scrolling to transition between a UIView and a UITableView
A PageView, which supporting scrolling to transition between a UIView and a UITableView

YXTPageView ##A Page View, which support scrolling to transition between a UIView and a UITableView UIView (at the top) UITableView (at the bottom) In

May 25, 2022
INTUZ is presenting an interesting a Multilevel Expand/Collapse UITableView App Control to integrate inside your native iOS-based application
INTUZ is presenting an interesting a Multilevel Expand/Collapse UITableView App Control to integrate inside your native iOS-based application

INTUZ is presenting an interesting a Multilevel Expand/Collapse UITableView App Control to integrate inside your native iOS-based application. MultilevelTableView is a simple component, which lets you use the tableview with multilevel tree view in your project.

Sep 21, 2021
a TableView have thumbnail cell only, and you can use gesture let it expands other expansionView, all diy
a TableView have thumbnail cell only, and you can use gesture let it expands other expansionView, all diy

ZYThumbnailTableView #####可展开型预览TableView,开放接口,完全自由定制 #####An expandable preview TableView, custom-made all the modules completely with open API you c

Jul 14, 2022
Simple and beautiful stacked UIView to use as a replacement for an UITableView, UIImageView or as a menu
Simple and beautiful stacked UIView to use as a replacement for an UITableView, UIImageView or as a menu

VBPiledView simple but highly effective animation and interactivity! By v-braun - viktor-braun.de. Preview Description Very simple and beautiful stack

May 16, 2022
Easy UITableView drag-and-drop cell reordering
Easy UITableView drag-and-drop cell reordering

SwiftReorder NOTE: Some users have encountered compatibility issues when using this library with recent versions of iOS. For apps targeting iOS 11 and

Jul 26, 2022
Elegant and easy way to integrate pagination with dummy views
Elegant and easy way to integrate pagination with dummy views

AZTableView Controller Features Automatic pagination handling No more awkward empty TableView screen AZ TableView controller give you advantage to con

May 16, 2022
TableViews - Emoji Table View For iOS With Swift
TableViews - Emoji Table View For iOS With Swift

TableViews Hello! This is EmojiTableView. Let me introduce you my first app when

Jan 2, 2022
A waterfall grid layout view for SwiftUI.
A waterfall grid layout view for SwiftUI.

WaterfallGrid A waterfall grid layout view for SwiftUI. Features Irregular grid of content. Columns number different per device orientation. Spacing a

Aug 11, 2022
🎛 QGrid: The missing SwiftUI collection view.
🎛 QGrid: The missing SwiftUI collection view.

[NOTE] If you'd like to see QGrid in action, check out this demo of QDesigner (see video below). Install QDesigner: https://apps.apple.com/us/app/qdes

Aug 7, 2022
A flexible grid layout view for SwiftUI
A flexible grid layout view for SwiftUI

?? GridStack A flexible grid layout view for SwiftUI. WWDC20 Update Apple  released LazyVGrid and LazyHGrid at WWDC20. If you are fine to only suppor

Aug 2, 2022
Display list of Marvel comic Characters and its detail view
Display list of Marvel comic Characters and its detail view

Marvel Universe Display list of Marvel comic Characters and its detail view Installation Dependencies in this project are provided via Xcodegen (proje

Oct 19, 2021
Building An Interactive Grid View
 Building An Interactive Grid View

Building An Interactive Grid View This demo shows a few techniques on how to build a re-ordable grid view based on stock UICollectionView API. Here ar

Jul 26, 2022