滑动删除和“更多”button(如在iOS 7上的邮件应用程序)

如何在用户在表格视图中滑动单元格时创build“更多”button(如ios 7中的邮件应用程序)

我一直在这里和Cocoa Touch论坛寻找这方面的信息,但我似乎无法find答案,我希望有人比我更聪明可以给我一个解决scheme。

我想,当用户滑动一个表格视图单元格,显示多个编辑button(他默认是删除button)。 在iOS 7的邮件应用程序中,您可以轻扫以删除,但是会显示一个“更多”button。

在这里输入图像说明

如何实施

它看起来像iOS 8打开这个API。 Beta 2中提供了这种function的提示。

为了得到一些工作,在UITableView的委托上实现以下两个方法来获得所需的效果(请参阅要点)。

- tableView:editActionsForRowAtIndexPath: - tableView:commitEditingStyle:forRowAtIndexPath: 

已知的问题

该文件说tableView:commitEditingStyle:forRowAtIndexPath是:

“不使用UITableViewRowAction调用编辑动作 – 动作的处理程序将被调用。”

但是,如果没有它,那么刷卡就不行。 即使方法存根是空白的,现在仍然需要它。 这显然是beta 2中的一个bug。

来源

https://twitter.com/marksands/status/481642991745265664 https://gist.github.com/marksands/76558707f583dbb8f870

原始答案: https : //stackoverflow.com/a/24540538/870028

更新:

示例代码与此工作(在Swift中): http : //dropbox.com/s/0fvxosft2mq2v5m/DeleteRowExampleSwift.zip

示例代码在MasterViewController.swift中包含了这个易于使用的方法,并且只需使用此方法即可获得OP屏幕截图中显示的行为:

 override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? { var moreRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "More", handler:{action, indexpath in println("MORE•ACTION"); }); moreRowAction.backgroundColor = UIColor(red: 0.298, green: 0.851, blue: 0.3922, alpha: 1.0); var deleteRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Delete", handler:{action, indexpath in println("DELETE•ACTION"); }); return [deleteRowAction, moreRowAction]; } 

我创build了一个新的库来实现swippablebutton,它支持各种转换和可扩展的button,如iOS 8邮件应用程序。

https://github.com/MortimerGoro/MGSwipeTableCell

这个库兼容所有不同的方式来创build一个UITableViewCell,并在iOS 5,iOS 6,iOS 7和iOS 8上testing。

这里是一些转换的例子:

边界过渡:

边界过渡

剪辑过渡

剪辑过渡

3D转换:

在这里输入图像说明

如何实施

iOS 8打开了这个API。

为了得到这个工作,在你的UITableView的委托上实现以下两个方法来获得所需的效果(参见代码示例)。

 - tableView:editActionsForRowAtIndexPath: - tableView:commitEditingStyle:forRowAtIndexPath: 

已知的问题

UITableView.h文件说明关于tableView的以下内容:commitEditingStyle:forRowAtIndexPath

“不使用UITableViewRowAction调用编辑动作 – 动作的处理程序将被调用。”

但是,如果没有它,则不会启用刷卡。 这似乎是一个错误。

来源

https://twitter.com/marksands/status/481642991745265664 https://gist.github.com/marksands/76558707f583dbb8f870

示例代码:

这是基于默认的主要细节应用程序模板(它在Swift中): http : //dropbox.com/s/0fvxosft2mq2v5m/DeleteRowExampleSwift.zip

约翰尼的回答是正确的回答。 我只是在Objective-C中添加下面的内容,以使初学者(以及我们这些拒绝学习Swift语法的人)更加清楚:

确保你声明了uitableviewdelegate并有以下方法:

  -(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewRowAction *button = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 1" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) { NSLog(@"Action to perform with Button 1"); }]; button.backgroundColor = [UIColor greenColor]; //arbitrary color UITableViewRowAction *button2 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 2" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) { NSLog(@"Action to perform with Button2!"); }]; button2.backgroundColor = [UIColor blueColor]; //arbitrary color return @[button, button2]; //array with all the buttons you want. 1,2,3, etc... } - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { // you need to implement this method too or nothing will work: } - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { return YES; //tableview must be editable or nothing will work... } 

这是(相当可笑)一个私人的API。

以下两种方法是私有的,并发送给UITableView的委托:

 -(NSString *)tableView:(UITableView *)tableView titleForSwipeAccessoryButtonForRowAtIndexPath:(NSIndexPath *)indexPath; -(void)tableView:(UITableView *)tableView swipeAccessoryButtonPushedForRowAtIndexPath:(NSIndexPath *)indexPath; 

他们很自我解释。

我希望你不能等到苹果给你什么你需要的权利? 所以这是我的select。

创build一个自定义单元格 有两个uiviews在里面

 1. upper 2. lower 

在较低的视图中,添加您需要的button。 像其他IBActions一样处理其行为。 你可以决定animation的时间,风格和任何东西。

现在添加一个uiswipegesture到上面的视图,并显示你的下视图的滑动手势。 我已经这样做了,就我而言,这是最简单的select。

希望有所帮助。

为了改进Johnny的答案,现在可以使用公共API完成如下操作:

 func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? { let moreRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "More", handler:{action, indexpath in print("MORE•ACTION"); }); moreRowAction.backgroundColor = UIColor(red: 0.298, green: 0.851, blue: 0.3922, alpha: 1.0); let deleteRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "Delete", handler:{action, indexpath in print("DELETE•ACTION"); }); return [deleteRowAction, moreRowAction]; } 

这是不可能使用标准的SDK。 然而,有不同的第三方解决scheme或多或less地模仿Mail.app中的行为。 其中一些(例如MCSwipeTableViewCell , DAContextMenuTableViewController , RMSwipeTableViewCell )使用手势识别器检测滑动,其中一些(例如SWTableViewCell )在标准UITableViewCellScrollViewUITableViewCellScrollView专用子视图)之下放置第二个UISScrollView,其中一些修改UITableViewCellScrollView的行为。

我最喜欢最后的方法,因为触摸处理感觉最自然。 具体而言, MSCMoreOptionTableViewCell是好的。 您的select可能会有所不同,具体取决于您的具体需求(无论您是否需要从左到右的平移,是否需要iOS 6兼容性等)。 另外请注意,大多数这些方法都带来一个负担:如果Apple在UITableViewCell子视图层次结构中进行更改,他们可以轻松地在未来的iOS版本中打破。

你需要willTransitionToState:(UITableViewCellStateMask)state UITableViewCell和子类的方法willTransitionToState:(UITableViewCellStateMask)statestate标志会告诉你是否显示删除button,并在那里显示/隐藏你的更多button。

不幸的是,这个方法既没有给你删除button的宽度也没有animation的时间。 所以你需要观察器和硬编码更多button的帧和animation时间到你的代码(我个人认为苹果公司需要做一些这方面的事情)。

Swift 3版本代码不使用任何库:

 import UIKit class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { @IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. tableView.tableFooterView = UIView(frame: CGRect.zero) //Hiding blank cells. tableView.separatorInset = UIEdgeInsets.zero tableView.dataSource = self tableView.delegate = self } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 4 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) return cell } //Enable cell editing methods. func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { return true } func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { } func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? { let more = UITableViewRowAction(style: .normal, title: "More") { action, index in //self.isEditing = false print("more button tapped") } more.backgroundColor = UIColor.lightGray let favorite = UITableViewRowAction(style: .normal, title: "Favorite") { action, index in //self.isEditing = false print("favorite button tapped") } favorite.backgroundColor = UIColor.orange let share = UITableViewRowAction(style: .normal, title: "Share") { action, index in //self.isEditing = false print("share button tapped") } share.backgroundColor = UIColor.blue return [share, favorite, more] } } 

快速编程

 func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { if editingStyle == UITableViewCellEditingStyle.Delete { deleteModelAt(indexPath.row) self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic) } else if editingStyle == UITableViewCellEditingStyle.Insert { println("insert editing action") } } func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? { var archiveAction = UITableViewRowAction(style: .Default, title: "Archive",handler: { (action: UITableViewRowAction!, indexPath: NSIndexPath!) in // maybe show an action sheet with more options self.tableView.setEditing(false, animated: false) } ) archiveAction.backgroundColor = UIColor.lightGrayColor() var deleteAction = UITableViewRowAction(style: .Normal, title: "Delete", handler: { (action: UITableViewRowAction!, indexPath: NSIndexPath!) in self.deleteModelAt(indexPath.row) self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic); } ); deleteAction.backgroundColor = UIColor.redColor() return [deleteAction, archiveAction] } func deleteModelAt(index: Int) { //... delete logic for model } 

这可以帮助你。

 -(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewRowAction *button = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 1" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) { NSLog(@"Action to perform with Button 1"); }]; button.backgroundColor = [UIColor greenColor]; //arbitrary color UITableViewRowAction *button2 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 2" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) { NSLog(@"Action to perform with Button2!"); }]; button2.backgroundColor = [UIColor blueColor]; //arbitrary color return @[button, button2]; //array with all the buttons you want. 1,2,3, etc... } - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { // you need to implement this method too or nothing will work: } - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { return YES; //tableview must be editable or nothing will work... } 

我正在寻找添加相同的function,我的应用程序,并经过这么多不同的教程( raywenderlich是最好的DIY解决scheme)后,我发现苹果有它自己的UITableViewRowAction类,这是非常方便。

您必须将Tableview的锅炉点方法更改为:

 override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? { // 1 var shareAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Share" , handler: { (action:UITableViewRowAction!, indexPath:NSIndexPath!) -> Void in // 2 let shareMenu = UIAlertController(title: nil, message: "Share using", preferredStyle: .ActionSheet) let twitterAction = UIAlertAction(title: "Twitter", style: UIAlertActionStyle.Default, handler: nil) let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil) shareMenu.addAction(twitterAction) shareMenu.addAction(cancelAction) self.presentViewController(shareMenu, animated: true, completion: nil) }) // 3 var rateAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Rate" , handler: { (action:UITableViewRowAction!, indexPath:NSIndexPath!) -> Void in // 4 let rateMenu = UIAlertController(title: nil, message: "Rate this App", preferredStyle: .ActionSheet) let appRateAction = UIAlertAction(title: "Rate", style: UIAlertActionStyle.Default, handler: nil) let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil) rateMenu.addAction(appRateAction) rateMenu.addAction(cancelAction) self.presentViewController(rateMenu, animated: true, completion: nil) }) // 5 return [shareAction,rateAction] } 

您可以在本网站上find更多关于此的信息。 苹果自己的文档对改变背景颜色非常有用:

操作button的背景颜色。

声明OBJECTIVE-C @property(nonatomic,copy)UIColor * backgroundColor Discussion使用这个属性来指定你的button的背景颜色。 如果您未为此属性指定值,则UIKit会根据style属性中的值分配默认颜色。

可用性iOS 8.0及更高版本中提供。

如果你想改变button的字体,那就更棘手了。 我已经看到另一篇文章 。 为了提供代码和链接,这里是他们在那里使用的代码。 你必须改变button的外观。 你必须对tableviewcell做一个具体的引用,否则你会改变整个应用程序的button外观(我不想要,但你可能,我不知道:))

目标C:

 + (void)setupDeleteRowActionStyleForUserCell { UIFont *font = [UIFont fontWithName:@"AvenirNext-Regular" size:19]; NSDictionary *attributes = @{NSFontAttributeName: font, NSForegroundColorAttributeName: [UIColor whiteColor]}; NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString: @"DELETE" attributes: attributes]; /* * We include UIView in the containment hierarchy because there is another button in UserCell that is a direct descendant of UserCell that we don't want this to affect. */ [[UIButton appearanceWhenContainedIn:[UIView class], [UserCell class], nil] setAttributedTitle: attributedTitle forState: UIControlStateNormal]; } 

迅速:

  //create your attributes however you want to let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(UIFont.systemFontSize())] as Dictionary! //Add more view controller types in the [] UIButton.appearanceWhenContainedInInstancesOfClasses([ViewController.self]) 

这是最简单,最stream线版本恕我直言。 希望能帮助到你。

更新:这是Swift 3.0版本:

 func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? { var shareAction:UITableViewRowAction = UITableViewRowAction(style: .default, title: "Share", handler: {(action, cellIndexpath) -> Void in let shareMenu = UIAlertController(title: nil, message: "Share using", preferredStyle: .actionSheet) let twitterAction = UIAlertAction(title: "Twitter", style: .default, handler: nil) let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) shareMenu.addAction(twitterAction) shareMenu.addAction(cancelAction) self.present(shareMenu,animated: true, completion: nil) }) var rateAction:UITableViewRowAction = UITableViewRowAction(style: .default, title: "Rate" , handler: {(action, cellIndexpath) -> Void in // 4 let rateMenu = UIAlertController(title: nil, message: "Rate this App", preferredStyle: .actionSheet) let appRateAction = UIAlertAction(title: "Rate", style: .default, handler: nil) let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) rateMenu.addAction(appRateAction) rateMenu.addAction(cancelAction) self.present(rateMenu, animated: true, completion: nil) }) // 5 return [shareAction,rateAction] } 

实际Swift 3答案

这是您需要的唯一function。 自定义操作不需要CanEdit或CommitEditingStyle函数。

 func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? { let action1 = UITableViewRowAction(style: .default, title: "Action1", handler: { (action, indexPath) in print("Action1") }) action1.backgroundColor = UIColor.lightGray let action2 = UITableViewRowAction(style: .default, title: "Action2", handler: { (action, indexPath) in print("Action2") }) return [action1, action2] } 

这样做有点脆弱,不涉及私有API或构build自己的系统。 您正在对冲您的赌注,苹果公司不打破这一点,希望他们将发布一个API,你可以用这几行代码。

  1. KVO self.contentView.superview.layer.sublayer。 在init中执行此操作。 这是UIScrollView的图层。 你不能KVO'subviews'。
  2. 子视图更改时,请在scrollview.subviews中find删除确认视图。 这是在观察callback中完成的。
  3. 将视图的大小加倍,并在其唯一的子视图左侧添加一个UIButton。 这也是在观察callback中完成的。 删除确认视图的唯一子视图是删除button。
  4. (可选)UIButton事件应查找self.superview,直到findUITableView,然后调用您创build的数据源或委托方法,如tableView:commitCustomEditingStyle:forRowAtIndexPath :. 您可以通过使用[tableView indexPathForCell:self]find单元格的indexPath。

这也要求你实现标准的表视图编辑委托callback。

 static char kObserveContext = 0; @implementation KZTableViewCell { UIScrollView *_contentScrollView; UIView *_confirmationView; UIButton *_editButton; UIButton *_deleteButton; } - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { _contentScrollView = (id)self.contentView.superview; [_contentScrollView.layer addObserver:self forKeyPath:@"sublayers" options:0 context:&kObserveContext]; _editButton = [UIButton new]; _editButton.backgroundColor = [UIColor lightGrayColor]; [_editButton setTitle:@"Edit" forState:UIControlStateNormal]; [_editButton addTarget:self action:@selector(_editTap) forControlEvents:UIControlEventTouchUpInside]; } return self; } -(void)dealloc { [_contentScrollView.layer removeObserver:self forKeyPath:@"sublayers" context:&kObserveContext]; } -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if(context != &kObserveContext) { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; return; } if(object == _contentScrollView.layer) { for(UIView * view in _contentScrollView.subviews) { if([NSStringFromClass(view.class) hasSuffix:@"ConfirmationView"]) { _confirmationView = view; _deleteButton = [view.subviews objectAtIndex:0]; CGRect frame = _confirmationView.frame; CGRect frame2 = frame; frame.origin.x -= frame.size.width; frame.size.width *= 2; _confirmationView.frame = frame; frame2.origin = CGPointZero; _editButton.frame = frame2; frame2.origin.x += frame2.size.width; _deleteButton.frame = frame2; [_confirmationView addSubview:_editButton]; break; } } return; } } -(void)_editTap { UITableView *tv = (id)self.superview; while(tv && ![tv isKindOfClass:[UITableView class]]) { tv = (id)tv.superview; } id<UITableViewDelegate> delegate = tv.delegate; if([delegate respondsToSelector:@selector(tableView:editTappedForRowWithIndexPath:)]) { NSIndexPath *ip = [tv indexPathForCell:self]; // define this in your own protocol [delegate tableView:tv editTappedForRowWithIndexPath:ip]; } } @end 

有一个叫SwipeCellKit的惊人的库,它应该得到更多的认可。 在我看来,它比MGSwipeTableCell 。 后者并不完全复制邮件应用程序的单元格的行为,而SwipeCellKit却行。 看一看

这是一个简单的解决scheme。 它能够在UITableViewCell中显示和隐藏自定义的UIView。 显示逻辑包含在从UITableViewCell,BaseTableViewCell扩展的类中。

BaseTableViewCell.h

 #import <UIKit/UIKit.h> @interface BaseTableViewCell : UITableViewCell @property(nonatomic,strong)UIView* customView; -(void)showCustomView; -(void)hideCustomView; @end 

BaseTableViewCell.M

 #import "BaseTableViewCell.h" @interface BaseTableViewCell() { BOOL _isCustomViewVisible; } @end @implementation BaseTableViewCell - (void)awakeFromNib { // Initialization code } -(void)prepareForReuse { self.customView = nil; _isCustomViewVisible = NO; } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state } -(void)showCustomView { if(nil != self.customView) { if(!_isCustomViewVisible) { _isCustomViewVisible = YES; if(!self.customView.superview) { CGRect frame = self.customView.frame; frame.origin.x = self.contentView.frame.size.width; self.customView.frame = frame; [self.customView willMoveToSuperview:self.contentView]; [self.contentView addSubview:self.customView]; [self.customView didMoveToSuperview]; } __weak BaseTableViewCell* blockSelf = self; [UIView animateWithDuration:.5 animations:^(){ for(UIView* view in blockSelf.contentView.subviews) { CGRect frame = view.frame; frame.origin.x = frame.origin.x - blockSelf.customView.frame.size.width; view.frame = frame; } }]; } } } -(void)hideCustomView { if(nil != self.customView) { if(_isCustomViewVisible) { __weak BaseTableViewCell* blockSelf = self; _isCustomViewVisible = NO; [UIView animateWithDuration:.5 animations:^(){ for(UIView* view in blockSelf.contentView.subviews) { CGRect frame = view.frame; frame.origin.x = frame.origin.x + blockSelf.customView.frame.size.width; view.frame = frame; } }]; } } } @end 

要获得这个function,简单地从BaseTableViewCell扩展你的表格视图单元格。

接下来,实现UITableViewDelegate的Inside UIViewController创build两个手势识别器来处理左右滑动。

 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self.tableView registerNib:[UINib nibWithNibName:CUSTOM_CELL_NIB_NAME bundle:nil] forCellReuseIdentifier:CUSTOM_CELL_ID]; UISwipeGestureRecognizer* leftSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleLeftSwipe:)]; leftSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionLeft; [self.tableView addGestureRecognizer:leftSwipeRecognizer]; UISwipeGestureRecognizer* rightSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleRightSwipe:)]; rightSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionRight; [self.tableView addGestureRecognizer:rightSwipeRecognizer]; } 

比添加两个滑动处理程序

 - (void)handleLeftSwipe:(UISwipeGestureRecognizer*)recognizer { CGPoint point = [recognizer locationInView:self.tableView]; NSIndexPath* index = [self.tableView indexPathForRowAtPoint:point]; UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:index]; if([cell respondsToSelector:@selector(showCustomView)]) { [cell performSelector:@selector(showCustomView)]; } } - (void)handleRightSwipe:(UISwipeGestureRecognizer*)recognizer { CGPoint point = [recognizer locationInView:self.tableView]; NSIndexPath* index = [self.tableView indexPathForRowAtPoint:point]; UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:index]; if([cell respondsToSelector:@selector(hideCustomView)]) { [cell performSelector:@selector(hideCustomView)]; } } 

现在,在UITableViewDelegate的cellForRowAtIndexPath中,您可以创build自定义的UIView并将其附加到已出队的单元格。

 -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { CustomCellTableViewCell* cell = (CustomCellTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"CustomCellTableViewCell" forIndexPath:indexPath]; NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:@"CellCustomView" owner:nil options:nil]; CellCustomView* customView = (CellCustomView*)[ nibViews objectAtIndex: 0]; cell.customView = customView; return cell; } 

当然,这种加载自定义UIView的方式就是这个例子。 pipe理它,如你所愿。

从iOS 11开始,这在UITableViewDelegate是公开的。 以下是一些示例代码:

 - (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath { UIContextualAction *delete = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive title:@"DELETE" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) { NSLog(@"index path of delete: %@", indexPath); completionHandler(YES); }]; UIContextualAction *rename = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal title:@"RENAME" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) { NSLog(@"index path of rename: %@", indexPath); completionHandler(YES); }]; UISwipeActionsConfiguration *swipeActionConfig = [UISwipeActionsConfiguration configurationWithActions:@[rename, delete]]; swipeActionConfig.performsFirstActionWithFullSwipe = NO; return swipeActionConfig; } 

Also available:

- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath;

Docs: https://developer.apple.com/documentation/uikit/uitableviewdelegate/2902367-tableview?language=objc

斯威夫特4

 func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { let delete = UIContextualAction(style: .destructive, title: "Delete") { (action, sourceView, completionHandler) in print("index path of delete: \(indexPath)") completionHandler(true) } let rename = UIContextualAction(style: .normal, title: "Edit") { (action, sourceView, completionHandler) in print("index path of edit: \(indexPath)") completionHandler(true) } let swipeActionConfig = UISwipeActionsConfiguration(actions: [rename, delete]) swipeActionConfig.performsFirstActionWithFullSwipe = false return swipeActionConfig } 

Swift 4 & iOs 11+

 @available(iOS 11.0, *) override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { let delete = UIContextualAction(style: .destructive, title: "Delete") { _, _, handler in handler(true) // handle deletion here } let more = UIContextualAction(style: .normal, title: "More") { _, _, handler in handler(true) // handle more here } return UISwipeActionsConfiguration(actions: [delete, more]) }