¿Cómo anular la selección de una celda seleccionada de UITableView?


212

Estoy trabajando en un proyecto en el que tengo que preseleccionar una celda en particular.

Puedo preseleccionar una celda usando -willDisplayCell, pero no puedo deseleccionarla cuando el usuario hace clic en cualquier otra celda.

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

¿Puede usted ayudar?


11
Esta pregunta debe tener una respuesta aceptada
Titouan de Bailleul

Respuestas:


407

usa este código

- (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
Hay un didDeselectRowAtIndexPath para usar para deseleccionar el anterior.
huggie

3
Me gusta pensar que no puedo votar esta publicación porque causaría un desbordamiento de enteros :)
Milo

hola @ram, debes seleccionar una respuesta a esta pregunta
Fattie

44
No entiendo ... este código nunca permitirá que se seleccione nada.
C. Tewalt

@matrixugly tiene razón. Es más apropiado hacer esto adentro willSelectRowAt:. Vea una respuesta más completa aquí: stackoverflow.com/questions/12693402/…
HuaTham

117

Use el siguiente método en la vista de tabla de delegados didSelectRowAtIndexpath(O desde cualquier lugar)

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

2
Vale la pena señalar que indexPathForSelectedRowes un método y no una propiedad.
FreeAsInBeer

¡Dulce! No sabía sobre [myTable indexPathForSelectedRow]. Estaba recorriendo las celdas antes. ¡Gracias!
guptron

@FreeAsInBeer ¿Es esta distinción importante de alguna manera? Los accesores de propiedad son métodos.
devios1

@chaiguy Está bien si no te importa que tus colegas te consideren malvado .
FreeAsInBeer

1
@Supertecnoboff No hay diferencia en el rendimiento entre las dos variaciones.
FreeAsInBeer

38

Prueba esto:

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

1
Buen trabajo ... Creo que 'index' en la segunda línea debería ser indexPath
El Tomato

esto no es compatible con iOS 11 Swift 4
Boris Nikolic

30

Puede ser útil hacer una extensión en Swift para esto.

Swift 4 y Swift 5:

Extensión Swift (por ejemplo, en un archivo UITableViewExtension.swift):

import UIKit

extension UITableView {

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

}

Utilice, por ejemplo:

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

    self.tableView.deselectSelectedRow(animated: true)
}

1
En mi opinión, esta respuesta es mejor porque poner la desolación en el viewWillAppear()método ayuda al usuario a comprender de dónde regresa.
MonsieurDart

el perfecto como lo necesitaba
Patel Jigar

28

Verifique con el método delegado si es correcto o no. Por ejemplo;

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

para

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

Estuve llamando al método equivocado todo este tiempo, ¡¡arghh !! ¡Gracias!
Damir Kotoric

1
oh hombre ... ¡autocompletado sangriento! ¡Me tomó varias horas resolverlo! Dios mío ... quiero besarte!
George Asda

22

Swift 4:

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

No necesita ser declarado no opcional, pero esto es correcto.
Michael

16

Esta es una solución para Swift 4

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

solo agrega

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

funciona a las mil maravillas

ejemplo:

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

hasta que agregue selección al editar en su vista de tabla, será imposible seleccionar cualquier celda porque la
anulará cuando termine de

Este es ciertamente el enfoque correcto, cuando no estás editando, cuando estás "tocando una fila para hacer algo"
Fattie

11

Además de configurar la celda como seleccionada, también debe informar a tableView que la celda está seleccionada. Agregue una llamada a -tableView:selectRowAtIndexPath:animated:scrollPosition:su willDisplayCell:método: y podrá anular su selección 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];   
    } 
}

Asegúrese de usar UITableViewScrollPositionNone para evitar comportamientos de desplazamiento extraños.


1
Absolutamente correcto. Creo que [cell setSelected:YES]podría omitirse: selectRowAtIndexPathse encargará del selectedestado de la célula
spassas

Esta respuesta funciona para UITableView's con múltiples selecciones. Pulgares hacia arriba.
Danny Bravo el

6

Esto debería funcionar:

[tableView deselectRowAtIndexPath:indexpath1 animated:NO];

Solo asegúrese de que materialTable y tableView estén apuntando al mismo objeto.

¿Están los materiales conectados a tableView en Interface Builder?


He probado con NO pero eso tampoco resuelve mi problema. pero solucioné este problema de otra manera cuando volví a cargar los datos cuando el delegado didselect disparaba
Ram

6

Basado en la solución de saikirans, he escrito esto, lo que me ayudó. En el archivo .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];

}

Y en el archivo de encabezado:

@property (retain, nonatomic) NSIndexPath* selectedRowIndex;

Tampoco tengo mucha experiencia, así que verifique si hay pérdidas de memoria, etc.


6

Si desea seleccionar cualquier celda de la tabla con el primer clic y deseleccionar con el segundo, debe usar este código:

- (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
Esto funcionó para mí en Swift 3. Sólo tuvo que añadir self.tableView(tableView, didDeselectRowAt: indexPath)después tableView.deselectRow...porque no se llama automáticamente
elysch

4

Swift 2.0:

tableView.deselectRowAtIndexPath(indexPath, animated: true)

3

prueba esto

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

intenta explicar tu respuesta, de lo contrario debería ser un comentario.
Hugo Dozois

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

coloque este código de acuerdo con su código y obtendrá su celda deseleccionada.


3

¿Puedes probar esto?

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

Funcionó para mi.


2

Swift 3.0:

Siguiendo la sección de conformidad del protocolo de la guía de estilo rápido de ray wenderlich , para mantener los métodos relacionados agrupados, coloque esta extensión debajo de su clase de controlador de vista de esa manera:

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

Rápido

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

También me he encontrado con esto: cuando navegas o vuelves a la vista de tabla, generalmente no anula la selección de la fila seleccionada anteriormente para ti. Puse este código en el controlador de vista de tabla y funciona bien:

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

1

Swift 3/4

En ViewController:

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

En celda personalizada:

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


0

Para que se desactive la selección de (DidDeselectRowAt) al hacer clic la primera vez debido a los datos precargados; debe informar a tableView que la fila ya está seleccionada para comenzar, de modo que un clic inicial luego deseleccione la fila:

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

Lo que he encontrado es que además de configurar la celda como seleccionada , debe informar a la vista de tabla para seleccionar la fila en la ruta de índice dada.

// 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)
    }
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.