如何在TableView中启用滑动删除单元格?

75

我有一个 UIViewController,实现了TableView的delegate和datasource协议。现在我想给单元格添加"滑动删除"手势。

我该如何做呢?

我已经提供了commitEditingStyle方法的空白实现,并将Editing属性设置为YES。

但仍然没有出现滑动功能。

现在我需要单独为每个单元格添加UISwipeGesture吗?

还是我漏掉了什么?


请参考以下链接,可能会对您有所帮助:https://dev59.com/wHA75IYBdhLWcg3waIQJ - Sharme
2
我已经重写了commitEditingStyle并将Editing设置为YES,现在我也重写了CanEditRowAtIndexPath。正常的编辑控件会出现,点击删除按钮即可。但是滑动不行! 这是因为我的类是UIViewController的子类,只实现了委托和数据源方法,而没有实现UITableViewController的方法,后者可能会执行一些操作以启用滑动手势。 - Amogh Talpallikar
昨天我在UIViewController中设置了一个UITableView作为IBOutlet,按照我展示的那篇文章的步骤,我实现了滑动删除功能。因此,我可以说你不需要启用滑动手势,但如果你真的无法通过其他方式使其工作,你可能不得不采取这种方法。 - gurooj
顺便提一句,问题已经解决了。我实际上覆盖了editingStyleForRowAtIndexPath方法,当表格不处于编辑模式时,它返回None,这就是问题所在。 我之前添加那个方法是为了某件事情,但当需求改变时忘记将其删除。 - Amogh Talpallikar
Swift 4: https://iosdevcenters.blogspot.com/2018/01/table-swipe-actions-in-swift-4-using.html - Bhadresh
13个回答

61

正如Dan上面所评论的,您需要实现以下表视图委托方法:

  1. tableView:canEditRowAtIndexPath:
  2. tableView:commitEditingStyle:forRowAtIndexPath:

注意:我已经在iOS 6和iOS 7中尝试过此方法。

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return YES - we will be able to delete all rows
    return YES;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Perform the real delete action here. Note: you may need to check editing style
    //   if you do not perform delete only.
    NSLog(@"Deleted row.");
}

3
我已在iPhone 6上的iOS 8.1.2中进行了测试,它可以正常工作。我只需要实现“- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath”方法,因为默认情况下应该启用编辑模式。 - Kramer

55

如果你需要在单元格滑动时显示删除按钮,就不必设置 editing:YES。相反,你需要实现tableView:canEditRowAtIndexPath:方法,并从其中返回想要编辑/删除的行的YES。当tableView的数据源是UITableViewContoller的子类时,这不是必需的 - 如果未覆盖此方法,则默认情况下它会返回YES。对于其他所有情况,你都需要实现它。

编辑:我们一起找到了问题所在 - 如果表格不处于编辑模式,tableView:editingStyleForRowAtIndexPath:会返回UITableViewCellEditingStyleNone


3
如果您不移除它,那么您的表格将进入编辑状态,此时滑动操作将无法使用。左侧的圆形红色减号按钮或滑动操作只能选择其中一个。 - Kyr Dunenkoff
1
现在我已经删除了setEditing语句,但是当我滑动时什么也没有发生。这是因为我使用的是UIViewController而不是TabelViewController,后者可能会默认添加滑动手势到每个单元格中。 - Amogh Talpallikar
5
我想补充一点,tableView:canEditRowAtIndexPath: 可能不够。您还需要实现 tableView:commitEditingStyle:forRowAtIndexPath - dwlz
当我滑动时,它会隐藏我的文本。我们能改变这种行为吗? - Durgaprasad
你应该移除这个方法。 - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath; - Hugo
显示剩余5条评论

25
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the specified item to be editable.
    return YES;
}



// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }   
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }   
}

6
对于像我这样的新手需要注意/评论:行仍然需要被删除,数据源(例如数组)也需要被缩减。 - BananaAcid

12
请尝试在Swift中使用此代码。
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
   // let the controller to know that able to edit tableView's row 
   return true
}

override func tableView(tableView: UITableView, commitEditingStyle editingStyle UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)  {
   // if you want to apply with iOS 8 or earlier version you must add this function too. (just left in blank code)
}

override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]?  {
   // add the action button you want to show when swiping on tableView's cell , in this case add the delete button.
   let deleteAction = UITableViewRowAction(style: .Default, title: "Delete", handler: { (action , indexPath) -> Void in

   // Your delete code here.....
   .........
   .........
   })

   // You can set its properties like normal button
   deleteAction.backgroundColor = UIColor.redColor()

   return [deleteAction]
}

5
尝试将以下内容添加到您的类中:
// Override to support conditional editing of the table view.
- (BOOL) tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    return(YES);
}

5
对我来说不起作用 :( 这是因为我的类是UIViewController的子类,我需要做一些额外的东西,UITabelViewController有吗? - Amogh Talpallikar
1
@AmoghTalpallikar,你是怎么解决问题的?能否发布你的解决方案?我也遇到了同样的问题。我的类是UIViewController的子类,tableView中所有的cell都是UITableViewCell的子类。 - Shamsiddin Saidov

3
Kyr Dunenkoff聊天的结论是:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {

}

如果您需要在滑动时出现删除按钮,则不应定义它。

1
如果您正在使用NSFetchedResultsControllerDelegate来填充表视图,这对我有效:
  • Make sure tableView:canEditRowAtIndexPath returns true always
  • In your tableView:commitEditingStyle:forRowAtIndexPath implementation, do not delete the row directly from the table view. Instead, delete it using your managed object context, e.g.:

    if editingStyle == UITableViewCellEditingStyle.Delete {
        let word = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Word
        self.managedObjectContext.deleteObject(word)
        self.saveManagedObjectContext()
    }
    
    func saveManagedObjectContext() {
        do {
            try self.managedObjectContext.save()
        } catch {
            let saveError = error as NSError
            print("\(saveError), \(saveError.userInfo)")
        }
    }
    

0

这是 Swift 版本

// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    // Return NO if you do not want the specified item to be editable.
    return true
}

// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == .Delete {
        // Delete the row from the data source
        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
    } else if editingStyle == .Insert {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }    
}

0
根据我的经验,似乎你必须将UITableViewediting设置为NO才能使滑动生效。 self.tableView.editing = NO;

0
这对我也是个问题...我只能在尝试10次左右才能让滑动删除起作用。原来电视上的gesture被父视图控制器中的另一个手势阻塞了。电视嵌套在一个MMDrawerController(可滑动抽屉布局)中。
只需在抽屉控制器中配置手势识别器,使其不响应侧边抽屉中的关闭手势,就可以让我的电视上的滑动删除功能正常工作。
您还可以尝试使用gesture delegate进行类似的操作:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}

我知道这已经很老了,但我遇到了与MMDrawerController完全相同的问题。您能详细说明一下“在抽屉控制器中配置手势识别器以不响应侧面抽屉中的关闭手势,从而允许滑动删除在我的电视上工作”吗?您如何做到这一点? - Mark

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接