Come deselezionare una cella UITableView selezionata?


212

Sto lavorando a un progetto su cui devo preselezionare una cella particolare.

Posso preselezionare una cella usando -willDisplayCell, ma non posso deselezionarla quando l'utente fa clic su qualsiasi altra cella.

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

Puoi aiutare?


11
Questa domanda deve avere una risposta accettata
Titouan de Bailleul,

Risposte:


408

usa questo codice

- (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
C'è un didDeselectRowAtIndexPath da usare per deselezionare quello precedente.
Huggie,

3
Mi piace pensare di non poter votare questo post perché causerebbe un overflow di numeri interi :)
Milo,

ciao @ram, devi selezionare una risposta a questa domanda
Fattie

4
Non capisco ... questo codice non consentirà mai di selezionare nulla.
C. Tewalt,

@matrixugly ha ragione. È più appropriato farlo all'interno willSelectRowAt:. Vedere una risposta più completa qui: stackoverflow.com/questions/12693402/...
HuaTham

117

Utilizzare il seguente metodo nei delegati della vista tabella didSelectRowAtIndexpath(o da qualsiasi luogo)

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

2
Vale la pena notare che indexPathForSelectedRowè un metodo e non una proprietà.
FreeAsInBeer,

Dolce! Non lo sapevo [myTable indexPathForSelectedRow]. Prima stavo attraversando le celle. Grazie!
guptron,

@FreeAsInBeer Questa distinzione è importante in qualche modo? Gli accessori di proprietà sono metodi.
devios1

@chaiguy Va bene se non ti dispiace che i tuoi colleghi ti considerino malvagio .
FreeAsInBeer,

1
@Supertecnoboff Non c'è differenza nelle prestazioni tra le due varianti.
FreeAsInBeer

38

Prova questo:

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

1
Ottimo lavoro ... Penso che "indice" sulla seconda riga dovrebbe essere indexPath
El Tomato

questo non è supportato su iOS 11 Swift 4
Boris Nikolic il

30

Per questo potrebbe essere utile creare un'estensione in Swift.

Swift 4 e Swift 5:

Estensione Swift (ad es. In un file UITableViewExtension.swift):

import UIKit

extension UITableView {

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

}

Usa ad esempio:

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

    self.tableView.deselectSelectedRow(animated: true)
}

1
Secondo me, questa risposta è migliore perché mettere la desolazione nel viewWillAppear()metodo aiuta l'utente a capire da dove ritorna.
Monsieur,

quello perfetto di cui avevo bisogno
Patel Jigar il

28

Verificare con il metodo delegato se è corretto o meno. Per esempio;

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

per

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

Stavo chiamando il metodo sbagliato per tutto questo tempo, arghh !! Grazie!
Damir Kotoric,

1
oh amico .... maledetto completamento automatico !!! Mi ci sono volute diverse ore per capirlo !!! OMG ... Voglio baciarti!
George Asda,

22

Swift 4:

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

Non ha bisogno di essere dichiarato non opzionale ma questo è corretto.
Michael,

16

Questa è una soluzione per Swift 4

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

basta aggiungere

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

Esso funziona magicamente

esempio:

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

fino a quando non aggiungi la selezione sulla modifica nella vista tabella, sarà impossibile selezionare qualsiasi cella perché la deselezionerà quando hai finito di selezionarla :)
Mehdi Chennoufi

Questo è certamente l'approccio corretto, quando non stai modificando, quando "
tocchi

11

Oltre a impostare la cella come selezionata, è anche necessario informare tableView che la cella è selezionata. Aggiungi una chiamata al -tableView:selectRowAtIndexPath:animated:scrollPosition:tuo willDisplayCell:metodo: e sarai in grado di deselezionarlo normalmente.

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

Assicurarsi di utilizzare UITableViewScrollPositionNone per evitare comportamenti di scorrimento dispari.


1
Assolutamente corretto. Penso che [cell setSelected:YES]potrebbe essere omesso: selectRowAtIndexPathsi prenderà cura della cella selecteddi stato
spassas

Questa risposta funziona per UITableView con più selezioni. Pollice su.
Danny Bravo,

6

Questo dovrebbe funzionare:

[tableView deselectRowAtIndexPath:indexpath1 animated:NO];

Assicurati solo che materialTable e tableView puntino allo stesso oggetto.

I materiali sono collegati al tableView in Interface Builder?


ho provato con NO ma anche questo non risolve il mio problema. ma ho risolto questo problema in un altro modo come dati ricaricati quando il delegato didselect veniva licenziato.
Ram

6

Sulla base della soluzione saikirans, ho scritto questo, che mi ha aiutato. Nel file .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];

}

E sul file di intestazione:

@property (retain, nonatomic) NSIndexPath* selectedRowIndex;

Neanche io ho molta esperienza, quindi ricontrolla le perdite di memoria ecc.


6

Se si desidera selezionare una cella di tabella con il primo clic e deselezionare con il secondo, è necessario utilizzare questo codice:

- (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
Questo ha funzionato per me a Swift 3. Basta dovuto aggiungere self.tableView(tableView, didDeselectRowAt: indexPath)dopo tableView.deselectRow...perché non è stato chiamato automaticamente
elysch

4

Swift 2.0:

tableView.deselectRowAtIndexPath(indexPath, animated: true)

3

prova questo

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

prova a spiegare la tua risposta, altrimenti dovrebbe essere un commento.
Hugo Dozois,

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

posiziona questo codice in base al tuo codice e otterrai la tua cella deselezionata.


3

Puoi provare questo?

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

Ha funzionato per me.


2

Swift 3.0:

Seguendo la sezione di conformità del protocollo della guida di stile rapido di Ray Wenderlich , per mantenere raggruppati i metodi correlati, metti questa estensione sotto la classe del controller della vista in questo modo:

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

veloce

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

Mi sono imbattuto anche in questo: quando navighi o ti rilassi alla vista della tabella di solito non deseleziona la riga precedentemente selezionata per te. Ho inserito questo codice nel controller della vista tabella e funziona bene:

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

1

Swift 3/4

In ViewController:

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

Nella cella personalizzata:

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


0

Per deselezionare (DidDeselectRowAt) il fuoco quando si fa clic per la prima volta a causa di dati precaricati; devi informare tableView che la riga è già selezionata per iniziare, quindi un clic iniziale deseleziona la riga:

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

Quello che ho trovato è che oltre a impostare la cella come selezionata , devi far sapere alla tabella di selezionare la riga nel percorso dell'indice indicato.

// 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)
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.