在 UITableViewCell
上滑动时如何显示删除按钮?该事件永远不会引发,删除按钮永远不会出现。
UITableViewCell
创建滑动删除操作的多达 3 种不同方式。
在 (-viewDidLoad or in storyboard)
启动期间,请执行以下操作:
self.tableView.allowsMultipleSelectionDuringEditing = false
覆盖以支持表格视图的条件编辑。仅当您要为某些项目返回 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
}
}
此答案已更新为 Swift 3
我一直认为有一个非常简单、自包含的示例是很好的,这样当我学习一项新任务时就不会假设任何事情。这个答案是删除 UITableView
行。该项目执行如下:
https://i.stack.imgur.com/sCoUS.gif
此项目基于 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
添加到情节提要中的视图控制器。使用自动布局将表格视图的四个边固定到视图控制器的边缘。控制从情节提要中的表格视图拖动到代码中的 @IBOutlet var tableView: UITableView!
行。
完成的
就这样。您现在应该能够运行您的应用程序并通过向左滑动并点击“删除”来删除行。
变化
更改“删除”按钮文本
https://i.stack.imgur.com/OfzBt.png
添加以下方法:
func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
return "Erase"
}
自定义按钮操作
https://i.stack.imgur.com/G5RPZ.png
添加以下方法。
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])
}
进一步阅读
如何使用操作制作可滑动的表格视图单元格 - 不使用滚动视图疯狂
文档
UITableView
one,但这是一个完全独立的项目,您无需执行此处未描述的任何操作。我开始在代码中设置它的原因是我的答案需要较少的解释。我也应该回去编辑基本示例以使用代码。
这段代码展示了如何实现删除。
#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;
我遇到了一个我刚刚设法解决的问题,所以我分享它,因为它可能对某人有所帮助。
我有一个 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;
有了这条线,多选就可以了,但滑动删除就不行了。没有这条线,情况正好相反。
修复:
将以下方法添加到您的 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];
这意味着只有在表格处于编辑模式时才启用多选。
下面的 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];
}
}
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()
}
}
在 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]
}
@Kurbz 的回答很棒,但我想留下这个便条,希望这个回答可以为人们节省一些时间。
我的控制器中偶尔会有这些线,它们使滑动功能不起作用。
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewCellEditingStyleNone;
}
如果您使用 UITableViewCellEditingStyleInsert
或 UITableViewCellEditingStyleNone
作为编辑样式,则滑动功能不起作用。您只能使用 UITableViewCellEditingStyleDelete
,这是默认样式。
斯威夫特 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]
}
此外,这可以在 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)
}
}
斯威夫特 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()
}
}
我知道这是个老问题,但@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];
}
当您删除 tableview 的一个单元格时,您还必须删除索引 x 处的数组对象。
我认为您可以使用滑动手势将其删除。表格视图将调用委托:
- (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 数组中删除对象,委托函数是不够的。
我希望我对你有所帮助。
[tableView reloadData]
调用 [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]
。
- (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];
}
}
如果您采用 diffable 数据源,则必须将委托回调移动到 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)
}
}
}
}
斯威夫特 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
}
对于 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]
}
斯威夫特 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]
}
对于 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);
}
}
SWIFT 5:适用于 iOS 13+
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .destructive, title: "Delete") { (contextualAction, view, boolValue) in
//Code I want to do here
}
let editAction = UIContextualAction(style: .destructive, title: "Edit") { (contextualAction, view, boolValue) in
//Code I want to do here
}
let swipeActions = UISwipeActionsConfiguration(actions: [deleteAction, editAction])
return swipeActions
}
self.tableView.allowsMultipleSelectionDuringEditing = NO;
才能使左滑起作用。这对我来说听起来像是一个错误,因为该表未处于编辑状态。此选项应仅适用于“编辑期间”。但是,它现在可以工作了,只要表格进入编辑状态,我就将其设置为 YES。