Comment désélectionner une cellule UITableView sélectionnée?


212

Je travaille sur un projet sur lequel je dois présélectionner une cellule particulière.

Je peux présélectionner une cellule en utilisant -willDisplayCell , mais je ne peux pas la désélectionner lorsque l'utilisateur clique sur une autre cellule.

- (void)tableView:(UITableView*)tableView 
        willDisplayCell:(UITableViewCell*)cell
        forRowAtIndexPath:(NSIndexPath*)indexPath
{ 
    AppDelegate_iPad *appDelegte = 
      (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];

    if ([appDelegte.indexPathDelegate row] == [indexPath row])
    {
        [cell setSelected:YES];    
    } 
}

- (void)tableView:(UITableView *)tableView 
        didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    AppDelegate_iPad *appDelegte = 
      (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];

    NSIndexPath *indexpath1 = appDelegte.indexPathDelegate;
    appDelegte.indexPathDelegate = indexPath;
    [materialTable deselectRowAtIndexPath:indexpath1 animated:NO];
}

Pouvez-vous m'aider?


11
Cette question doit avoir une réponse acceptée
Titouan de Bailleul

Réponses:


408

utilisez ce code

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
 {
    //Change the selected background view of the cell.
     [tableView deselectRowAtIndexPath:indexPath animated:YES];
 }

Swift 3.0:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    //Change the selected background view of the cell.
    tableView.deselectRow(at: indexPath, animated: true)
}

1
Il existe un didDeselectRowAtIndexPath à utiliser pour désélectionner le précédent.
huggie

3
J'aime à penser que je ne peux pas voter sur ce post car cela provoquerait un débordement d'entier :)
Milo

salut @ram, vous devez sélectionner une réponse à cette question
Fattie

4
Je ne comprends pas ... ce code ne laissera jamais rien être sélectionné.
C.Tewalt

@matrixugly a raison. Il est plus approprié de le faire à l'intérieur willSelectRowAt:. Voir une réponse plus complète ici: stackoverflow.com/questions/12693402/…
HuaTham

117

Utilisez la méthode suivante dans le délégué de vue de table didSelectRowAtIndexpath(ou de n'importe où)

[myTable deselectRowAtIndexPath:[myTable indexPathForSelectedRow] animated:YES];

2
Il convient de noter qu'il indexPathForSelectedRows'agit d'une méthode et non d'une propriété.
FreeAsInBeer

Doux! Je ne savais pas [myTable indexPathForSelectedRow]. Je parcourais les cellules avant. Merci!
guptron

@FreeAsInBeer Cette distinction est-elle importante d'une manière ou d'une autre? Les accesseurs de propriété sont des méthodes.
devios1

@chaiguy C'est bien si cela ne vous dérange pas que vos collègues vous considèrent mal .
FreeAsInBeer

1
@Supertecnoboff Il n'y a pas de différence de performances entre les deux variantes.
FreeAsInBeer

38

Essaye ça:

for (NSIndexPath *indexPath in tableView.indexPathsForSelectedRows) {
    [tableView deselectRowAtIndexPath:indexPath animated:NO];
}

1
Bon travail ... Je pense que 'index' sur la 2e ligne devrait être indexPath
El Tomato

cela n'est pas pris en charge sur iOS 11 Swift 4
Boris Nikolic

30

Il pourrait être utile de faire une extension dans Swift pour cela.

Swift 4 et Swift 5:

Extension Swift (par exemple dans un fichier UITableViewExtension.swift):

import UIKit

extension UITableView {

    func deselectSelectedRow(animated: Bool)
    {
        if let indexPathForSelectedRow = self.indexPathForSelectedRow {
            self.deselectRow(at: indexPathForSelectedRow, animated: animated)
        }
    }

}

Utilisez par exemple:

override func viewWillAppear(_ animated: Bool)
{
    super.viewWillAppear(animated)

    self.tableView.deselectSelectedRow(animated: true)
}

1
À mon avis, cette réponse est meilleure car mettre la désolation dans la viewWillAppear()méthode aide l'utilisateur à comprendre d'où il vient.
MonsieurDart

le parfait comme j'avais besoin
Patel Jigar

28

Veuillez vérifier avec la méthode déléguée si elle est correcte ou non. Par exemple;

-(void) tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath

pour

-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

J'appelais la mauvaise méthode pendant tout ce temps, arghh !! Je vous remercie!
Damir Kotoric

1
oh man .... sanglant autocomplétion !!! Il m'a fallu plusieurs heures pour le comprendre !!! OMG ... je veux t'embrasser!
George Asda

22

Swift 4:

tableView.deselectRow(at: indexPath, animated: true)

N'a pas besoin d'être déclaré non facultatif mais c'est correct.
Michael

16

Ceci est une solution pour Swift 4

 in tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)

il suffit d'ajouter

tableView.deselectRow(at: indexPath, animated: true)

il fonctionne comme un charme

exemple:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
//some code
}

tant que vous n'ajoutez pas de sélection lors de l'édition dans votre table, il sera impossible de sélectionner une cellule car elle la désélectionnera lorsque vous aurez fini de la sélectionner :)
Mehdi Chennoufi

C'est certainement la bonne approche, lorsque vous n'éditez pas, lorsque vous "appuyez sur une ligne pour faire quelque chose"
Fattie

11

En plus de définir la cellule comme sélectionnée, vous devez également informer la tableView que la cellule est sélectionnée. Ajouter un appel à-tableView:selectRowAtIndexPath:animated:scrollPosition: votre willDisplayCell:méthode: vous pourrez la désélectionner normalement.

- (void)tableView:(UITableView*)tableView 
  willDisplayCell:(UITableViewCell*)cell
forRowAtIndexPath:(NSIndexPath*)indexPath
{ 
    AppDelegate_iPad *appDelegte = (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];

    if ([appDelegte.indexPathDelegate row] == [indexPath row])
    {
        // SELECT CELL
        [cell setSelected:YES]; 
        // TELL TABLEVIEW THAT ROW IS SELECTED
        [tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];   
    } 
}

Assurez-vous d'utiliser UITableViewScrollPositionNone pour éviter un comportement de défilement étrange.


1
Absolument correct. Je pense que cela [cell setSelected:YES]pourrait être omis: selectRowAtIndexPaths'occupera de l' selectedétat de la cellule
spassas

Cette réponse fonctionne pour UITableView avec plusieurs sélections. Pouces vers le haut.
Danny Bravo

6

Cela devrait fonctionner:

[tableView deselectRowAtIndexPath:indexpath1 animated:NO];

Assurez-vous simplement que materialTable et tableView pointent vers le même objet.

Les matériaux sont-ils connectés à la tableView dans Interface Builder?


j'ai testé avec NON mais cela ne résout pas non plus mon problème. mais j'ai résolu ce problème d'une autre manière en tant que données rechargées chaque fois que le délégué didselect tirait.
Ram

6

Basé sur la solution des saikirans, j'ai écrit ceci, ce qui m'a aidé. Sur le fichier .m:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    if(selectedRowIndex && indexPath.row == selectedRowIndex.row) {

        [tableView deselectRowAtIndexPath:indexPath animated:YES];
        selectedRowIndex = nil;

    }

    else {  self.selectedRowIndex = [indexPath retain];   }

    [tableView beginUpdates];
    [tableView endUpdates];

}

Et sur le fichier d'en-tête:

@property (retain, nonatomic) NSIndexPath* selectedRowIndex;

Je ne suis pas très expérimenté non plus, donc vérifiez bien les fuites de mémoire, etc.


6

Si vous souhaitez sélectionner une cellule de tableau avec le premier clic et désélectionner avec le second, vous devez utiliser ce code:

- (void)tableView:(UITableView *)tableView 
        didSelectRowAtIndexPath:(NSIndexPath *)indexPath {   

    if (self.selectedIndexPath && 
        [indexPath compare:self.selectedIndexPath] == NSOrderedSame) {

        [tableView deselectRowAtIndexPath:indexPath animated:YES];
         self.selectedIndexPath = nil;
    } 
    else {
        self.selectedIndexPath = indexPath;
    }
}

5

Swift 4:

func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    let cell = tableView.cellForRow(at: indexPath)
    if cell?.isSelected == true { // check if cell has been previously selected
        tableView.deselectRow(at: indexPath, animated: true)
        return nil
    } else {
        return indexPath
    }
}

2
Cela a fonctionné pour moi dans Swift 3. Il suffit d'ajouter self.tableView(tableView, didDeselectRowAt: indexPath)après tableView.deselectRow...parce qu'il n'a pas été appelé automatiquement
elysch

4

Swift 2.0:

tableView.deselectRowAtIndexPath(indexPath, animated: true)

3

essaye ça

[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];

essayez d'expliquer votre réponse, sinon ce devrait être un commentaire.
Hugo Dozois

3
NSIndexPath * index = [self.menuTableView indexPathForSelectedRow];
[self.menuTableView deselectRowAtIndexPath:index animated:NO];

placez ce code selon votre code et vous obtiendrez votre cellule désélectionnée.


3

Peux-tu essayer ça?

- (void)tableView:(UITableView *)tableView 
  didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    AppDelegate_iPad *appDelegte = 
    (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];
    NSIndexPath *indexpath1 = appDelegte.indexPathDelegate;
    appDelegte.indexPathDelegate = indexPath;

    UITableViewCell *prevSelectedCell = [tableView cellForRowAtIndexPath: indexpath1];
    if([prevSelectedCell isSelected]){
       [prevSelectedCell setSelected:NO];
    }
}

Ça a marché pour moi.


2

Swift 3.0:

En suivant la section sur la conformité au protocole du guide de style de Ray Wenderlich Swift , pour regrouper les méthodes associées, placez cette extension sous votre classe de contrôleur de vue comme ça:

// your view controller
class MyViewcontroller: UIViewController {
  // class stuff here
}

// MARK: - UITableViewDelegate
extension MyViewcontroller: UITableViewDelegate {
      // use the UITableViewDelegate method tableView(_:didSelectRowAt:)
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        // your code when user select row at indexPath

        // at the end use deselectRow
        tableView.deselectRow(at: indexPath, animated: true)
    }
}

1

Rapide

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    // your code

    // your code

    // and use deselect row to end line of this function

    self.tableView.deselectRowAtIndexPath(indexPath, animated: true)

}

1
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
}

1

Swift 3

J'ai également rencontré cela - lorsque vous naviguez ou vous retournez à la vue tableau, il ne désélectionne généralement pas la ligne précédemment sélectionnée pour vous. J'ai mis ce code dans le contrôleur de vue de table et cela fonctionne bien:

override func viewDidAppear(_ animated: Bool) {
    if let lastSelectedRow = tableView.indexPathForSelectedRow {
        tableView.deselectRow(at: lastSelectedRow, animated: true)
    }
}

1

Swift 3/4

Dans ViewController:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
}

Dans une cellule personnalisée:

override func awakeFromNib() {
    super.awakeFromNib()
    selectionStyle = .none
}


0

Pour que la désélection (DidDeselectRowAt) se déclenche lorsque vous cliquez dessus pour la première fois en raison de données préchargées; vous devez informer la tableView que la ligne est déjà sélectionnée pour commencer, de sorte qu'un premier clic désélectionne ensuite la ligne:

// Swift 3:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if tableView[indexPath.row] == "data value"

        tableView.selectRow(at: indexPath, animated: false, scrollPosition: UITableViewScrollPosition.none)

    }
}

0

Ce que j'ai trouvé, c'est qu'en plus de définir la cellule comme sélectionnée , vous devez informer la vue de table pour sélectionner la ligne au chemin d'index donné.

// Swift 3+  

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if appDelegate.indexPathDelegate.row == indexPath.row {
        self.tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
        cell.setSelected(true, animated: true)
    }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.