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?

RAM
la source
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)
}
Saikiran K
la source
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];
Shamitha
la source
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];
}
ikosdroid
la source
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)
}
Thomas Neuteboom
la source
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
jfalexvijay
la source
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)
Andrea.Ferrando
la source
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
}
tBug
la source
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.

Drew C
la source
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?

Jordan
la source
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.

Yunus Nedim Mehel
la source
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;
    }
}
CHiP-love-NY
la source
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
    }
}
Serguei Vinnitskii
la source
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)
Anit Kumar
la source
3

essaye ça

[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
EnasAZ
la source
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.

rahulchona
la source
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.

Dattatraya Anarase
la source
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)
    }
}
ronatoire
la source
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)

}
Programer_saeed
la source
1
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
}
Aayushi
la source
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)
    }
}
Trev14
la source
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
}
Sevy11
la source
0

swift 3.0

    tableView.deselectRow(at: indexPath, animated: true)
Marcelo Gracietti
la source
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)

    }
}
Arkelyan
la source
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)
    }
}
David Para
la source