首页 文章

UITableViewCell,在滑动时显示删除按钮

提问于
浏览
541

如何在 UITableViewCell 上滑动时如何显示删除按钮?永远不会引发该事件,并且永远不会出现删除按钮 .

17 回答

  • 34

    这个答案已更新为Swift 3

    我总是认为拥有一个非常简单,自包含的例子是很好的,这样当我学习新任务时就不会有任何假设 . 这个答案是删除 UITableView 行 . 该项目执行如下:

    enter image description here

    该项目基于UITableView example for Swift .

    添加代码

    创建一个新项目并使用以下代码替换ViewController.swift代码 .

    import UIKit
    class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
        // These strings will be the data for the table view cells
        var animals: [String] = ["Horse", "Cow", "Camel", "Pig", "Sheep", "Goat"]
    
        let cellReuseIdentifier = "cell"
    
        @IBOutlet var tableView: UITableView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // It is possible to do the following three things in the Interface Builder
            // rather than in code if you prefer.
            self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)
            tableView.delegate = self
            tableView.dataSource = self
        }
    
        // number of rows in table view
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return self.animals.count
        }
    
        // create a cell for each table view row
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
            let cell:UITableViewCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as UITableViewCell!
    
            cell.textLabel?.text = self.animals[indexPath.row]
    
            return cell
        }
    
        // method to run when table view cell is tapped
        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            print("You tapped cell number \(indexPath.row).")
        }
    
        // this method handles row deletion
        func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    
            if editingStyle == .delete {
    
                // remove the item from the data model
                animals.remove(at: indexPath.row)
    
                // delete the table view row
                tableView.deleteRows(at: [indexPath], with: .fade)
    
            } else if editingStyle == .insert {
                // Not used in our example, but if you were adding a new row, this is where you would do it.
            }
        }
    
    }
    

    上面代码中允许行删除的单键方法是最后一个 . 这里再次强调:

    // this method handles row deletion
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    
        if editingStyle == .delete {
    
            // remove the item from the data model
            animals.remove(at: indexPath.row)
    
            // delete the table view row
            tableView.deleteRows(at: [indexPath], with: .fade)
    
        } else if editingStyle == .insert {
            // Not used in our example, but if you were adding a new row, this is where you would do it.
        }
    }
    

    故事板

    在故事板中将 UITableView 添加到View Controller . 使用自动布局将表视图的四边固定到View Controller的边缘 . 控制从故事板中的表视图拖动到代码中的 @IBOutlet var tableView: UITableView! 行 .

    完了

    就这样 . 您应该能够立即运行您的应用并通过向左滑动并点按“删除”来删除行 .


    变化

    Change the "Delete" button text

    enter image description here

    添加以下方法:

    func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
        return "Erase"
    }
    

    Custom button actions

    enter image description here

    添加以下方法 .

    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    
        // action one
        let editAction = UITableViewRowAction(style: .default, title: "Edit", handler: { (action, indexPath) in
            print("Edit tapped")
        })
        editAction.backgroundColor = UIColor.blue
    
        // action two
        let deleteAction = UITableViewRowAction(style: .default, title: "Delete", handler: { (action, indexPath) in
            print("Delete tapped")
        })
        deleteAction.backgroundColor = UIColor.red
    
        return [editAction, deleteAction]
    }
    

    请注意,这仅适用于iOS 8.有关详细信息,请参阅this answer .

    针对iOS 11进行了更新

    可以使用添加到iOS 11中的UITableViewDelegate API的方法将操作置于前导或尾随单元格 .

    func tableView(_ tableView: UITableView,
                    leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
     {
         let editAction = UIContextualAction(style: .normal, title:  "Edit", handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in
                 success(true)
             })
    editAction.backgroundColor = .blue
    
             return UISwipeActionsConfiguration(actions: [editAction])
     }
    
     func tableView(_ tableView: UITableView,
                    trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
     {
         let deleteAction = UIContextualAction(style: .normal, title:  "Delete", handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in
             success(true)
         })
         deleteAction.backgroundColor = .red
    
         return UISwipeActionsConfiguration(actions: [deleteAction])
     }
    

    进一步阅读

  • 2

    我有一个问题,我刚刚设法解决,所以我分享它,因为它可以帮助某人 .

    我有一个UITableView并添加了显示的方法以启用滑动删除:

    - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
        // Return YES if you 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) {
            //add code here for when you hit delete
        }    
    }
    

    我正在进行一项更新,允许我将表格置于编辑模式并启用多选 . 为此,我添加了Apple的TableMultiSelect示例中的代码 . 一旦我开始工作,我发现我的刷卡删除功能已停止工作 .

    事实证明,向viewDidLoad添加以下行是问题:

    self.tableView.allowsMultipleSelectionDuringEditing = YES;
    

    使用此行,多选将起作用,但删除的滑动不会 . 没有这条线就是另一种方式 .

    The fix:

    将以下方法添加到viewController:

    - (void)setEditing:(BOOL)editing animated:(BOOL)animated
    {
        self.tableView.allowsMultipleSelectionDuringEditing = editing; 
        [super setEditing:editing animated:animated];
    }
    

    然后在您将表格置于编辑模式的方法中(例如,按下按钮),您应该使用:

    [self setEditing:YES animated:YES];
    

    代替:

    [self.tableView setEditing:YES animated:YES];
    

    这意味着仅当表处于编辑模式时才启用多选 .

  • 8

    在iOS 8和Swift 2.0中,请试试这个,

    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, commitEdittingStyle 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]
    }
    
  • 17

    Swift 2.2:

    override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        return true
    }
    
    override func tableView(tableView: UITableView,
        editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
        let delete = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "DELETE"){(UITableViewRowAction,NSIndexPath) -> Void in
    
        print("Your action when user pressed delete")
    }
    let edit = UITableViewRowAction(style: UITableViewRowActionStyle.Normal, title: "EDIT"){(UITableViewRowAction,NSIndexPath) -> Void in
    
        print("Your action when user pressed edit")
    }
        return [delete, block]
    }
    
  • 89

    @Kurbz的答案很棒,但我想留下这个说明,希望这个答案可以节省一些时间 .

    我偶尔在我的控制器中有这些线,他们使滑动功能无法正常工作 .

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

    如果使用 UITableViewCellEditingStyleInsertUITableViewCellEditingStyleNone 作为编辑样式,则滑动功能不起作用 . 您只能使用 UITableViewCellEditingStyleDelete ,这是默认样式 .

  • 17

    此代码显示了如何实现删除 .

    #pragma mark - UITableViewDataSource
    
    // Swipe to delete.
    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if (editingStyle == UITableViewCellEditingStyleDelete) {
            [_chats removeObjectAtIndex:indexPath.row];
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
        }
    }
    

    (可选)在初始化覆盖中,添加下面的行以显示“编辑”按钮项:

    self.navigationItem.leftBarButtonItem = self.editButtonItem;
    
  • 68

    删除tableview的单元格时,还必须删除索引x处的数组对象 .

    我认为您可以使用滑动手势将其删除 . 表视图将调用Delegate:

    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
        if (editingStyle == UITableViewCellEditingStyleDelete) {
            //add code here for when you hit delete
            [dataSourceArray removeObjectAtIndex:indexPath.row];
        }    
    }
    

    删除对象后 . 您必须重新加载tableview使用 . 在代码中添加以下行:

    [tableView reloadData];
    

    之后,您已成功删除该行 . 当您重新加载视图或向DataSource添加数据时,对象将不再存在 .

    对于所有其他人来说,Kurbz的答案是正确的 .

    我只想提醒您,如果要从DataSource数组中删除对象,则委托函数是不够的 .

    我希望我能帮助你 .

  • 2

    注意:我没有足够的声誉在Kurbz的答案中发表评论 .

    Kurbz的答案是对的 . 但对我来说它从来没有奏效 .

    经过一番调查,我意识到 swipe-to-delete happens when NOT editing the table view. .

    我从未见过如此明确说明的 . 除非我弄错了,否则我没有找到任何其他办法让它发挥作用 .

    编辑时,将显示删除和/或重新排序控件 .

  • 1007
    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
    {
        if (editingStyle == UITableViewCellEditingStyleDelete)
        {
            //add code here for when you hit delete
            [dataSourceArray removeObjectAtIndex:indexPath.row];
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
        }    
    }
    
  • 6

    对于Swift,只需编写此代码即可

    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
            if editingStyle == .Delete {
                print("Delete Hit")
            }
    }
    

    对于Objective C,只需编写此代码即可

    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
           if (editingStyle == UITableViewCellEditingStyleDelete) {           
                NSLog(@"index: %@",indexPath.row);
               }
    }
    
  • 8

    我知道这是老问题,但@Kurbz回答只需要Xcode 6.3.2和SDK 8.3

    我需要添加 [tableView beginUpdates][tableView endUpdates] (感谢@ bay.phillips here

    // Override to support editing the table view.
    - (void)tableView:(UITableView *)tableView commitEditingStyle: (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
        // Open "Transaction"
        [tableView beginUpdates];
    
        if (editingStyle == UITableViewCellEditingStyleDelete) {
            // your code goes here
            //add code here for when you hit delete
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
         }
    
        // Close "Transaction"
        [tableView endUpdates];
    }
    
  • 2

    对于swift4代码,首先启用编辑:

    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        return true
    }
    

    然后你将删除操作添加到编辑委托:

    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
        let action = UITableViewRowAction(style: .destructive, title: "Delete") { (_, index) in
            // delete model object at the index
            self.models[index.row]
            // then delete the cell
            tableView.beginUpdates()
            tableView.deleteRows(at: [index], with: .automatic)
            tableView.endUpdates()
    
        }
        return [action]
    }
    
  • 6

    此外,这可以使用如下方法在SWIFT中实现

    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if (editingStyle == UITableViewCellEditingStyle.Delete){
            testArray.removeAtIndex(indexPath.row)
            goalsTableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
        }
    }
    
  • 8

    在启动期间 (-viewDidLoad or in storyboard) 执行:

    self.tableView.allowsMultipleSelectionDuringEditing = NO;
    

    覆盖以支持表视图的条件编辑 . 如果您要为某些项目返回 NO ,则只需要实现此功能 . 默认情况下,所有项目都是编辑 .

    - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
        // Return YES if you 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) {
            //add code here for when you hit delete
        }    
    }
    
  • 6

    Below UITableViewDataSource will help you for swipe delete

    - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
        // Return YES if you want the specified item to be editable.
        return YES;
    }
    
    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
        if (editingStyle == UITableViewCellEditingStyleDelete) {
            [arrYears removeObjectAtIndex:indexPath.row];
            [tableView reloadData];
        }
    }
    

    arrYears 是一个NSMutableArray,然后重新加载tableView

    Swift

    func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
                return true
            }
    
    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == UITableViewCellEditingStyleDelete {
            arrYears.removeObjectAtIndex(indexPath.row)
            tableView.reloadData()
        }
    }
    
  • 10

    斯威夫特3

    您所要做的就是启用以下两个功能:

    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    
        return true
    
    }
    
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    
        if editingStyle == UITableViewCellEditingStyle.delete {
            tableView.reloadData()
        }
    
    }
    
  • 24

    Swift 4

    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
        let delete = UITableViewRowAction(style: .destructive, title: "delete") { (action, indexPath) in
            // delete item at indexPath
        tableView.deleteRows(at: [indexPath], with: .fade)
    
        }
        return [delete]
    }
    

相关问题