web-dev-qa-db-fra.com

UITableViewCell, afficher le bouton Supprimer lors du balayage

Comment puis-je afficher le bouton de suppression lors du glissement sur un UITableViewCell? L'événement n'est jamais déclenché et le bouton Supprimer n'apparaît jamais.

553
TheLearner

Pendant le démarrage dans (-viewDidLoad or in storyboard) faire:

self.tableView.allowsMultipleSelectionDuringEditing = NO;

Remplacer pour prendre en charge l’édition conditionnelle de la vue tabulaire. Ceci ne doit être implémenté que si vous retournez NO pour certains éléments. Par défaut, tous les éléments sont modifiables.

- (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
    }    
}
1021
Kurbz

Cette réponse a été mise à jour pour Swift 3

Je pense toujours qu'il est agréable d'avoir un exemple très simple et autonome afin que rien ne soit supposé lorsque j'apprends une nouvelle tâche. Cette réponse est celle pour supprimer UITableView lignes. Le projet fonctionne comme ceci:

enter image description here

Ce projet est basé sur le exemple UITableView pour Swift .

Ajouter le code

Créez un nouveau projet et remplacez le code ViewController.Swift par le suivant.

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.
        }
    }

}

La méthode de clé unique dans le code ci-dessus qui permet la suppression de ligne est la dernière. La voici à nouveau pour souligner:

// 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.
    }
}

Storyboard

Ajoutez un UITableView au contrôleur de vue dans le storyboard. Utilisez la disposition automatique pour épingler les quatre côtés de la vue de table aux bords du contrôleur de vue. Faites glisser le contrôle depuis la vue de table du storyboard vers la ligne @IBOutlet var tableView: UITableView! du code.

Fini

C'est tout. Vous devriez pouvoir exécuter votre application maintenant et supprimer des lignes en faisant glisser votre doigt vers la gauche et en appuyant sur "Supprimer".


Variations

Modifiez le texte du bouton "Supprimer"

enter image description here

Ajoutez la méthode suivante:

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

Actions des boutons personnalisés

enter image description here

Ajoutez la méthode suivante.

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]
}

Notez que cela n’est disponible que sur iOS 8. Voir cette réponse pour plus de détails.

mis à jour pour iOS 11

Les actions peuvent être placées en tête ou en queue de la cellule à l'aide de méthodes ajoutées à l'API UITableViewDelegate dans iOS 11.

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])
 }

Lectures complémentaires

104
Suragch

Ce code montre comment implémenter la suppression.

#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];
    }
}

Eventuellement, dans votre remplacement d'initialisation, ajoutez la ligne ci-dessous pour afficher l'élément de bouton Modifier:

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

Note: Je n'ai pas assez de réputation pour poster un commentaire dans la réponse de Kurbz.

La réponse de Kurbz est juste. Mais pour moi cela n'a jamais fonctionné.

Après quelques recherches, je me suis rendu compte que n balayage pour supprimer se produit lorsque vous ne modifiez PAS la vue tabulaire..

Je n'ai jamais vu cela explicitement déclaré comme tel. Sauf erreur, je n'ai pas trouvé d'autre moyen de le faire fonctionner.

Lorsque vous modifiez, le contrôle de suppression et/ou de réorganisation apparaît.

34
GenesisST

J'ai eu un problème que je viens juste de résoudre, alors je le partage car cela peut aider quelqu'un.

J'ai un UITableView et ajouté les méthodes montrées pour permettre à glisser pour supprimer:

- (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
    }    
}

Je travaille sur une mise à jour qui me permet de mettre le tableau en mode édition et active multiselect. Pour ce faire, j'ai ajouté le code de l'exemple TableMultiSelect d'Apple. Une fois que j'ai eu ce travail, j'ai constaté que mon balayage la fonction de suppression avait cessé de fonctionner.

Il s'avère que l'ajout de la ligne suivante à viewDidLoad était le problème:

self.tableView.allowsMultipleSelectionDuringEditing = YES;

Avec cette ligne, le multisélection fonctionnerait, mais le balayage à supprimer ne fonctionnerait pas. Sans la ligne, c'était l'inverse.

Le correctif:

Ajoutez la méthode suivante à votre viewController:

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

Ensuite, dans votre méthode qui met la table en mode d’édition (à partir d’une pression sur un bouton, par exemple), vous devez utiliser:

[self setEditing:YES animated:YES];

au lieu de:

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

Cela signifie que la sélection multiple n'est activée que lorsque la table est en mode édition.

24
Leon

Ci-dessous UITableViewDataSource vous aidera à supprimer par glissement

- (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 est un NSMutableArray, puis rechargez la tableView

rapide

 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()
    }
}
18
iAnkit

Dans iOS 8 et Swift 2.0, essayez ceci,

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
Masa S-AiYa

La réponse de @ Kurbz est géniale, mais je souhaite laisser cette note et espère que cette réponse permettra aux gens de gagner du temps.

J'ai parfois eu ces lignes dans mon contrôleur, et ils ont fait la fonctionnalité de balayage ne fonctionne pas.

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

Si vous utilisez UITableViewCellEditingStyleInsert ou UITableViewCellEditingStyleNone comme style d'édition, la fonction de balayage ne fonctionne pas. Vous ne pouvez utiliser que UITableViewCellEditingStyleDelete, qui est le style par défaut.

11
Brian

Swift 3

Tout ce que vous avez à faire est d’activer ces deux fonctions:

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()
    }

}
8
Machado

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]
}
8
Pratik Lad

En outre, ceci peut être réalisé dans Swift en utilisant la méthode suivante

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
DrPatience

Je sais que c'est une vieille question, mais la réponse de @Kurbz en a simplement besoin pour Xcode 6.3.2 et SDK 8.3

J'ai besoin d'ajouter [tableView beginUpdates] et [tableView endUpdates] (merci à @ bay.phillips ici )

// 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];
}
7
Beto
- (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
Rahul K Rajan

Lorsque vous supprimez une cellule de votre table, vous devez également supprimer votre objet tableau à l'index x.

Je pense que vous pouvez l'enlever en effectuant un geste de balayage. La vue tableau appellera le délégué:

- (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];
    }    
}

Après avoir retiré l'objet. Vous devez recharger l'utilisation de tableview. Ajoutez la ligne suivante dans votre code:

[tableView reloadData];

après cela, vous avez supprimé la ligne avec succès. Et lorsque vous rechargez la vue ou ajoutez des données à la source de données, l'objet ne sera plus là.

Pour tous les autres, la réponse de Kurbz est correcte.

Je voulais seulement vous rappeler que la fonction de délégué ne sera pas suffisante si vous souhaitez supprimer l'objet du tableau DataSource.

J'espère vous avoir aidé.

6
Robybyte

Pour Swift, écrivez simplement ce code

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

Pour Objective C, écrivez simplement ce code

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

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]
}
2
lcl

pour le code Swift4, activez d'abord l'édition:

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

alors vous ajoutez une action de suppression au délégué d'édition:

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
Abdoelrhman