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

The*_*ner 560 cocoa-touch objective-c uitableview uikit ios

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

Kur*_*rbz 1025

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

self.tableView.allowsMultipleSelectionDuringEditing = NO;
Run Code Online (Sandbox Code Playgroud)

覆盖以支持表视图的条件编辑.如果您要返回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
    }    
}
Run Code Online (Sandbox Code Playgroud)

  • 这有效,但是...... - (BOOL)tableView:(UITableView*)tableView canEditRowAtIndexPath:(NSIndexPath*)indexPath ...只有在你要为某些项目返回NO时才需要实现.默认情况下,所有项目都是可编辑的,因此如果始终返回YES,则无需实现. (93认同)
  • 同样重要的是要知道:这些是UITableViewDataSource方法和**NOT**UITableViewDelegate方法. (24认同)
  • 只是要清楚 - 你必须覆盖tableView:commitEditingStyle:forRowAtIndexPath:或者无法识别滑动手势,当你尝试删除时什么也不会发生. (11认同)
  • 想知道[如何实施删除](http://stackoverflow.com/a/19885064/242933)? (8认同)

Sur*_*gch 109

这个答案已更新为Swift 3

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

在此输入图像描述

该项目基于SwiftUITableView示例.

添加代码

创建一个新项目并使用以下代码替换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.
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

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

// 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.
    }
}
Run Code Online (Sandbox Code Playgroud)

故事板

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

成品

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


变化

更改"删除"按钮文本

在此输入图像描述

添加以下方法:

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

自定义按钮操作

在此输入图像描述

添加以下方法.

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]
}
Run Code Online (Sandbox Code Playgroud)

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

针对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])
 }
Run Code Online (Sandbox Code Playgroud)

进一步阅读


ma1*_*w28 68

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

#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];
    }
}
Run Code Online (Sandbox Code Playgroud)

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

self.navigationItem.leftBarButtonItem = self.editButtonItem;
Run Code Online (Sandbox Code Playgroud)


Gen*_*sST 34

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

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

经过一些调查,我意识到在不编辑表格视图时会发生滑动到删除..

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

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


Leo*_*eon 24

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

我有一个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
    }    
}
Run Code Online (Sandbox Code Playgroud)

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

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

self.tableView.allowsMultipleSelectionDuringEditing = YES;
Run Code Online (Sandbox Code Playgroud)

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

修复:

将以下方法添加到viewController:

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

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

[self setEditing:YES animated:YES];
Run Code Online (Sandbox Code Playgroud)

代替:

[self.tableView setEditing:YES animated:YES];
Run Code Online (Sandbox Code Playgroud)

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


iAn*_*kit 18

UITableViewDataSource下方将帮助您进行滑动删除

- (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];
    }
}
Run Code Online (Sandbox Code Playgroud)

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

迅速

 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()
    }
}
Run Code Online (Sandbox Code Playgroud)


Mas*_*iYa 17

在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]
}
Run Code Online (Sandbox Code Playgroud)


Bri*_*ian 11

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

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

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
    return UITableViewCellEditingStyleNone; 
}
Run Code Online (Sandbox Code Playgroud)

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


小智 9

斯威夫特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]
}
Run Code Online (Sandbox Code Playgroud)


DrP*_*nce 8

此外,这可以使用如下方法在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)
    }
}
Run Code Online (Sandbox Code Playgroud)


Mac*_*ado 8

斯威夫特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()
    }

}
Run Code Online (Sandbox Code Playgroud)


Bet*_*eto 7

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

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

// 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];
}
Run Code Online (Sandbox Code Playgroud)


小智 6

删除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];
    }    
}
Run Code Online (Sandbox Code Playgroud)

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

[tableView reloadData];
Run Code Online (Sandbox Code Playgroud)

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

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

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

我希望我能帮助你.

  • 而不是调用`[tableView reloadData]`call [`[tableView deleteRowsAtIndexPaths:@ [indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]`](http://stackoverflow.com/a/19885064/242933). (4认同)

Rah*_*jan 6

- (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];
    }    
}    
Run Code Online (Sandbox Code Playgroud)


MAL*_*MAN 5

斯威夫特 4,5

要在滑动时删除单元格,UITableView 有两个内置方法。在 TableView 数据源扩展中编写此方法。

func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
  let delete = deleteProperty(at: indexPath)
  return UISwipeActionsConfiguration(actions: [delete])
}

// Declare this method in UIViewController Main and modify according to your need

func deleteProperty(at indexpath: IndexPath) -> UIContextualAction {
  let action = UIContextualAction(style: .destructive, title: "Delete") { (action, view, completon) in
    self.yourArray.remove(at: indexpath) // Removing from array at selected index

    completon(true)
    action.backgroundColor = .red //cell background color
  }
  return action
}
Run Code Online (Sandbox Code Playgroud)


Aus*_*lon 5

如果您采用可比较的数据源,则必须将委托回调移至子UITableViewDiffableDataSource类。例如:

class DataSource: UITableViewDiffableDataSource<SectionType, ItemType> {

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

    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            if let identifierToDelete = itemIdentifier(for: indexPath) {
                var snapshot = self.snapshot()
                snapshot.deleteItems([identifierToDelete])
                apply(snapshot)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)