全面轻扫UITableViewCell删除UITableView iOS 8

我想模仿滑动来删除UITableViewCell的function,就像iOS 8中的邮件应用程序。我不是指滑动来显示删除button。 我指的是当你滑动时,它会抛弃3个动作,但是如果你继续向左滑动,电子邮件将被删除。

在iOS 8中,UITableView有一个新的方法,你可以提供数据来显示任意数量的button:

#ifdef __IPHONE_8_0 - (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewRowAction *viewStackRowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Stack" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) { SM_LOG_DEBUG(@"View Stack Action"); }]; viewStackRowAction.backgroundColor = [UIColor radiusBlueColor]; UITableViewRowAction *viewUserRowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"User" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) { SM_LOG_DEBUG(@"View User Action"); }]; viewUserRowAction.backgroundColor = [UIColor radiusLightBlueColor]; UITableViewRowAction *deleteRowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Delete" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) { SM_LOG_DEBUG(@"Delete"); }]; deleteRowAction.backgroundColor = [UIColor redColor]; return @[deleteRowAction, viewUserRowAction, viewStackRowAction]; } #endif 

如果您继续滑动,则看不到任何API。 我已经在UITableView.h grepped 8_0和上述方法似乎是唯一的新的。

我想可以监视滚动视图偏移,或添加/劫持UIPanGestureRecognizer。 我只是想确保使用默认的方式,如果有(并获得“免费”的animation)

添加ui gustere识别器到每个单元格,检查“swipness”的数量,如果其上述特定的阈值,做删除。

类似于:

  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"identifier"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]]; } UISwipeGestureRecognizer* swipe_gesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeLeft:)]; [swipe_gesture setDirection:UISwipeGestureRecognizerDirectionLeft]; [cell addGestureRecognizer:swipe_gesture]; return cell; } - (void)swipeLeft:(UIGestureRecognizer *)gestureRecognizer { int threshold = 100; if (sender.state == UIGestureRecognizerStateBegan) { startLocation = [sender locationInView:self.view]; } else if (sender.state == UIGestureRecognizerStateEnded) { CGPoint stopLocation = [sender locationInView:self.view]; CGFloat dx = stopLocation.x - startLocation.x; CGFloat dy = stopLocation.y - startLocation.y; CGFloat distance = sqrt(dx*dx + dy*dy ); if (distance > threshold ) { NSLog(@"DELETE_ROW"); } } } 

您的表视图的数据源必须执行

 -tableView:commitEditingStyle:forRowAtIndexPath: 

否则内置的iOS 8刷卡function将不起作用。

这似乎违反直觉,因为UITableViewRowAction接受一个块。 但是这是我能够实现它的唯一方法。

您可以使用MGSwipeTableCell 。 他们已经实现这个function来触发callbackswipeTableCell:tappedButtonAtIndex:direction:fromExpansion:with tappedButtonAtIndex等于0(所以它得到执行你在第一个添加的button上实现的)。

使用Swift 4和iOS 11,根据您的需要,您可以select以下三种方法之一来创build尾部滑动操作,以删除所选的UITableViewCell


#1。 使用tableView(_:commit:forRowAt:)

 import UIKit class TableViewController: UITableViewController { var numbers = [Int](0..<10) override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return numbers.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = "\(numbers[indexPath.row])" return cell } override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { if (editingStyle == UITableViewCellEditingStyle.delete) { self.numbers.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .fade) } } } 

#2。 使用UITableViewRowAction

 import UIKit class TableViewController: UITableViewController { var numbers = [Int](0..<10) override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return numbers.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = "\(numbers[indexPath.row])" return cell } override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { // Intentionally blank in order to be able to use UITableViewRowActions } override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? { let deleteHandler: (UITableViewRowAction, IndexPath) -> Void = { _, indexPath in self.numbers.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .fade) } let deleteAction = UITableViewRowAction(style: UITableViewRowActionStyle.destructive, title: "Delete", handler: deleteHandler) // Add more actions here if required return [deleteAction] } } 

#3。 使用UIContextualAction (需要iOS 11)

 import UIKit class TableViewController: UITableViewController { var numbers = [Int](0..<10) override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return numbers.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = "\(numbers[indexPath.row])" return cell } override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { let handler: UIContextualActionHandler = { (action: UIContextualAction, view: UIView, completionHandler: ((Bool) -> Void)) in self.numbers.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .fade) completionHandler(true) } let deleteAction = UIContextualAction(style: UIContextualAction.Style.destructive, title: "Delete", handler: handler) // Add more actions here if required let configuration = UISwipeActionsConfiguration(actions: [deleteAction]) configuration.performsFirstActionWithFullSwipe = true // The default value of this property is true. return configuration } }