2011-04-04 16 views
10

Tengo un UITableView con cada fila que contiene una casilla de verificación usando UITableViewCellAccessoryCheckmark. No puedo encontrar la manera de desmarcar todas las casillas usando el método didSelectRowAtIndexPath.Cómo desmarcar todas las filas usando UITableViewCellAccessoryCheckmark

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

    UITableViewCell *oldCell; 

    int count = [self.myTableRowNamesArray count]; 

    for (NSUInteger i = 0; i < count; ++i) {         
     // Uncheck all checkboxes 
     // OF COURSE THIS DOESN'T WORK 
     // BECAUSE i IS AN INTEGER AND INDEXPATH IS A POINTER 
     FOO: oldCell = [myTableView cellForRowAtIndexPath:(int)i]; 
     // GOOD CODE: 
     oldCell = [penanceOptionsTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]]; 
     oldCell.accessoryType = UITableViewCellAccessoryNone; 
    } 
    UITableViewCell *newCell = [myTableView cellForRowAtIndexPath:indexPath]; 
    newCell.accessoryType = UITableViewCellAccessoryCheckmark; 
} 

Respuesta

4

Sí, cellForRowAtIndexPath: utiliza NSIndexPath en lugar de número entero así que indexpath utilizando

indexPathForRow:inSection: 

si está utilizando una sección a continuación, el bucle está bien sólo tiene que pasar en la fila i y 0 para la sección.

11
for (UITableViewCell *cell in [myTableView visibleCells]) { 
    cell.accessoryType = UITableViewCellAccessoryNone; 
} 

Pero realmente, sería mejor que simplemente modificando la celda que realmente tiene la marca de verificación establecida. De todos modos, debe haber almacenado esta información en algún lugar de su modelo.

+1

Eso es lo que quiero decir. Simplemente cambie la celda que tiene la marca de verificación establecida (y por supuesto la celda que se está convirtiendo en la nueva celda marcada). –

20

En lugar de modificar la .accessoryType de todas las células en didSelectRowAtIndexPath:, sugiero almacenar el índice seleccionado en algunos Ivar, y cambiar el .accessoryType en el método de la fuente de datos -tableView:cellForRowAtIndexPath:, es decir

-(void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath { 
    self.selectedIndexPath = indexPath; 
    [tableView reloadData]; 
} 

-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath { 
    ... 
    cell.accessoryType = [indexPath compare:self.selectedIndexPath] == NSOrderedSame 
          ? UITableViewCellAccessoryCheckmark 
          : UITableViewCellAccessoryNone; 
    ... 
} 

Con esto, solamente las celdas visibles se verán afectadas y no será necesario modificar el millón de celdas fuera de la pantalla.


Muy bien, esto es una implementación completa de Swift en el caso general de selección de una célula .. que tendría que utilizar selectedIndexPath en otra parte de la clase como mejor le parezca. Por ejemplo, en cellForRowAtIndexPath para elegir el prototipo de celda apropiado.

// SelectingTableViewController 

import UIKit 

class SelectingTableViewController: UITableViewController 
    { 
    internal var selectedIndexPath:NSIndexPath? = nil 

    override func viewDidLoad() 
     { 
     super.viewDidLoad() 
     tableView.estimatedRowHeight = 68.0 
     tableView.rowHeight = UITableViewAutomaticDimension 

     self.clearsSelectionOnViewWillAppear = false; 
     } 

    override func tableView 
     (tableView:UITableView, didSelectRowAtIndexPath indexPath:NSIndexPath) 
      { 
      print("did select....") 

      // in fact, was this very row selected, 
      // and the user is clicking to deselect it... 
      // if you don't want "click a selected row to deselect" 
      // then on't include this clause. 
      if selectedIndexPath == indexPath 
       { 
       print("(user clicked on selected to deselect)") 
       selectedIndexPath = nil 
       tableView.reloadRowsAtIndexPaths(
        [indexPath], 
        withRowAnimation:UITableViewRowAnimation.None) 

       tableView.deselectRowAtIndexPath(indexPath, animated:false) 
       return 
       } 

      // in fact, was some other row selected?? 
      // user is changing to this row? if so, also deselect that row 
      if selectedIndexPath != nil 
       { 
       let pleaseRedrawMe = selectedIndexPath! 
       // (note that it will be drawn un-selected 
       // since we're chaging the 'selectedIndexPath' global) 
       selectedIndexPath = indexPath 
       tableView.reloadRowsAtIndexPaths(
        [pleaseRedrawMe, indexPath], 
        withRowAnimation:UITableViewRowAnimation.None) 
       return; 
       } 

      // no previous selection. 
      // simply select that new one the user just touched. 
      // note that you can not use Apple's willDeselectRowAtIndexPath 
      // functions ... because they are freaky 
      selectedIndexPath = indexPath 
      tableView.reloadRowsAtIndexPaths(
       [indexPath], 
       withRowAnimation:UITableViewRowAnimation.None) 

      } 

    } 
+1

¿Llamar a [reloadData] varias veces causa algún efecto negativo? – onmyway133

+0

markotop superior (y) – tesmojones

5

Probablemente se esté estableciendo algún tipo de propiedad con este método. Así que lo que hago es:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    // 1. first unsetting the property 
    [object someProperty:nil]; 

    // 2. call the reloadData method to uncheck all the checkmarks 
    [tableView reloadData]; 

    // 3. check the selected cell 
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 
    [cell setAccessoryType:UITableViewCellAccessoryCheckmark]; 

    // 4. set the checked property 
    [object setSomeProperty:[indexpath row]]; 
} 

Y en mis métodos cellForRowAtIndexPath Tengo algo como el siguiente código:

if([object someProperty] == [indexpath row]){ 
     [cell setAccessoryType:UITableViewCellAccessoryCheckmark];   
    } else { 
     [cell setAccessoryType:UITableViewCellAccessoryNone]; 
    } 
Cuestiones relacionadas