✔ Marque la fila seleccionada en UITableViewCell

Soy un novato en desarrollo de iOS. Quiero agregar una marca de verificación a mi UITableViewCell cuando se selecciona. La marca de verificación debe eliminarse cuando se selecciona otra fila. ¿Cómo haría esto?

No use [tableview reloadData]; // es un martillo.

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark; } -(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone; } 

En su método UITableViewDatasource:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if(cell == nil ) { cell =[[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; } if ([indexPath compare:self.lastIndexPath] == NSOrdenetworkingSame) { cell.accessoryType = UITableViewCellAccessoryCheckmark; } else { cell.accessoryType = UITableViewCellAccessoryNone; } return cell; } // UITableView Delegate Method -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { self.lastIndexPath = indexPath; [tableView reloadData]; } 

Y lastIndexPath es una property(strong) NSIndexPath* lastIndexPath;

Descubrí que volver a cargar los datos interrumpe la animation deseleccionada de una manera fea.

Esta implementación Swift limpiamente agrega / quita marcas de verificación y anula la selección de la fila:

 func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { if self.lastSelection != nil { self.myTableView.cellForRowAtIndexPath(self.lastSelection)?.accessoryType = .None } self.myTableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .Checkmark self.lastSelection = indexPath self.myTableView.deselectRowAtIndexPath(indexPath, animated: true) } 

donde lastSelection se declara como var lastSelection: NSIndexPath!

No se necesita actividad adicional en cellForRowAtIndexPath . No debería ser difícil de replicar en Obj-C.

Para establecer una marca de verificación:

 UITableViewCell *cell = ...; cell.accessoryType = UITableViewCellAccessoryCheckmark; 

Para seleccionar / deseleccionar una celda:

 [cell setSelected:TRUE animated:TRUE]; // select [cell setSelected:FALSE animated:TRUE]; // deselect 

Para anular la selección de la celda anterior, use un ivar lastSelected NSIndexPath * para rastrear la última celda seleccionada:

 - (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath { if (self.lastSelected==indexPath) return; // nothing to do // deselect old UITableViewCell *old = [self.tableView cellForRowAtIndexPath:self.lastSelected]; old.accessoryType = UITableViewCellAccessoryNone; [old setSelected:FALSE animated:TRUE]; // select new UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; cell.accessoryType = UITableViewCellAccessoryCheckmark; [cell setSelected:TRUE animated:TRUE]; // keep track of the last selected cell self.lastSelected = indexPath; } 

pequeño error tipográfico

 // deselect old UITableViewCell *old = [self.tableView cellForRowAtIndexPath:self.lastSelected]; cell.accessoryType = UITableViewCellAccessoryNone; [cell setSelected:FALSE animated:TRUE]; 

tiene que leer

 // deselect old UITableViewCell *old = [self.tableView cellForRowAtIndexPath:self.lastSelected]; old.accessoryType = UITableViewCellAccessoryNone; [old setSelected:FALSE animated:TRUE]; 

y tambien en el

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == [previouslySelected intValue]) { cell.accessoryType = UITableViewCellAccessoryCheckmark; selectedIndex = indexPath; [cell setSelected:YES animated:YES]; } else { cell.accessoryType = UITableViewCellAccessoryNone; [cell setSelected:NO animated:YES]; } } 

donde previouslySelected es su ivar local, etc. de esta manera si vuelve a cargar con un índice seleccionado también se deselecciona cuando hojea las posibles selects.

Suponiendo que UITableViewController una class que henetworkinge de UITableViewController , este es el truco en Swift 3:

 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // Add a visual cue to indicate that the cell was selected. self.tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark } override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { // Invoked so we can prepare for a change in selection. // Remove previous selection, if any. if let selectedIndex = self.tableView.indexPathForSelectedRow { // Note: Programmatically deslecting does NOT invoke tableView(:didSelectRowAt:), so no risk of infinite loop. self.tableView.deselectRow(at: selectedIndex, animated: false) // Remove the visual selection indication. self.tableView.cellForRow(at: selectedIndex)?.accessoryType = .none } return indexPath } 

El código superior mencionado solo funciona con la única selección . Este código siguiente seguramente funcionará para selects múltiples .

 - (void)viewDidLoad { arrSelectionStatus =[NSMutableArray array]; //arrSelectionStatus holds the cell selection status for (int i=0; i<arrElements.count; i++) { //arrElements holds those elements which will be populated in tableview [arrSelectionStatus addObject:[NSNumber numberWithBool:NO]]; } } -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; if (cell==nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"]; } cell.textLabel.text=[arrElements objectAtIndex:indexPath.row]; if ([[arrSelectionStatus objectAtIndex:indexPath.row] boolValue] == YES) cell.accessoryType = UITableViewCellAccessoryCheckmark; else cell.accessoryType = UITableViewCellAccessoryNone; return cell; } -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; cell.accessoryType = UITableViewCellAccessoryCheckmark; [arrSelectionStatus replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:YES]]; } -(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; cell.accessoryType = UITableViewCellAccessoryNone; [arrSelectionStatus replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:NO]]; } 

Just Call didSelectRowAtIndexPath Method cuando selecciona cualquier fila para Mostrar CheckMark y Seleccionar la fila de marca para hide CheckMark.

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:true]; NSLog(@"touch"); UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; if (cell.accessoryType == UITableViewCellAccessoryNone) { cell.accessoryType = UITableViewCellAccessoryCheckmark; } else { cell.accessoryType = UITableViewCellAccessoryNone; } } 

Cuando una celda seleccionada (con la marca de verificación seleccionada nuevamente), simplemente elimine la selección.

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath { BOOL isSelected = ([tableView cellForRowAtIndexPath:indexPath].accessoryType == UITableViewCellAccessoryCheckmark); if(isSelected){ [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone; [tableView deselectRowAtIndexPath:indexPath animated:YES]; //this won't trigger the didDeselectRowAtIndexPath, but it's always a good idea to remove the selection }else{ [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark; } } - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath*)indexPath { [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone; } 

Prima:

Use self.tableView.indexPathForSelectedRow para detectar indexPath para la celda seleccionada

Las respuestas anteriores no funcionan si reutilizas la celda por una gran cantidad de datos. En el desplazamiento, puede ver una marca repetida. Para evitar usar los siguientes pasos:

  1. declarar en variable: var indexNumber: NSInteger = -1

  2. Agregue el código siguiente en cellforRowAtIndexPath:

      override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{ if indexNumber == indexPath.row{ cell.accessoryType = .checkmark }else{ cell.accessoryType = .none } } 
  3. Y en didselectAtIndexpath, agregue el siguiente código:

override func tableView (_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.cellForRow(at: indexPath as IndexPath)?.accessoryType = .checkmark indexNumber = indexPath.row } override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { tableView.cellForRow(at: indexPath as IndexPath)?.accessoryType = .none }