2011-04-13 11 views
31

iPad: ¿Iterar sobre cada celda en una UITableView?iPad: ¿Iterar sobre cada celda en una UITableView?

+4

Pregunta sin sentido, realmente: las células se agrupan y se vuelven a utilizar. Generalmente, si no lo ves en una pantalla, no existe. Elabora por favor sobre lo que estás tratando de hacer. –

+0

+1 para comentar, ¿por qué necesita iterar sobre las celdas? Por lo general, debe iterar sobre la estructura de datos subyacente de la que rellena las celdas. Si necesita acceder a las celdas por alguna razón, entonces en 'cellForRowAtIndexPath:' puede establecer una propiedad 'cell' de su estructura de datos subyacente para apuntar a la celda inicializada. Sin embargo, asegúrese de que sea un '@property (assign)', no un 'retain', ya que no desea mantener todas las celdas en la memoria por el bien de la reutilización. – darvids0n

+8

No es realmente sin sentido; el UITableView existe como una representación visual de algún datastore de respaldo. Y el almacén de datos existe independientemente de si un subconjunto particular de sus datos se encuentra actualmente en la pantalla. Así que iterar las celdas es comparable a consultar lo que hay en la tienda, una fila a la vez. – aroth

Respuesta

64
for (int section = 0; section < [tableView numberOfSections]; section++) { 
    for (int row = 0; row < [tableView numberOfRowsInSection:section]; row++) { 
     NSIndexPath* cellPath = [NSIndexPath indexPathForRow:row inSection:section]; 
     UITableViewCell* cell = [tableView cellForRowAtIndexPath:cellPath]; 
     //do stuff with 'cell' 
    } 
} 
+5

¡Solo funciona en celdas visibles! –

+5

Es normal que solo funcione en celdas visibles. Las células invisibles son quitadas de la memoria; cellForRowAtIndexPath devolverá nil para ellos. –

+0

@RaviSharma add [self.tableView scrollToRowAtIndexPath: indexPath atScrollPosition: UITableViewScrollPositionTop animated: NO]; y se usará en celdas no visibles. – zaolian

26

para iterar sobre cada célula visible en un UITableView:

for (UITableViewCell *cell in self.tableView.visibleCells) { 
    NSIndexPath *cellIndexPath = [self.tableView indexPathForCell:cell]; 

(editado a una mejor respuesta del estado y la esperanza de que esto está indexado con mayor precisión los resultados de búsqueda con la intención de salvar a otros más tiempo en el futuro)

+3

Eso es solo para celdas visibles. – darvids0n

+0

Debería haber dicho que actualicé mi respuesta para reflejar su comentario. – AndrewPK

+0

+1 para usar un estilo oop en lugar de un enfoque de función, aunque no necesitaría hacer esto a menos que esté actualizando el estilo de la GUI. –

2

Suponiendo una variable myTableView existe y su fuente delegado y los datos están establecidos:

UITableViewCell *cell; 
NSIndexPath indexPath = [[NSIndexPath indexPathForRow:0 inSection:0]; 
for(indexPath.section = 0; indexPath.section < [myTableView numberOfSections]; ++indexPath.section) 
{ 
    for(indexPath.row = 0; indexPath.row < [myTableView numberOfRowsInSection:indexPath.section]; ++indexPath.row) 
    { 
     cell = [myTableView cellForRowAtIndexPath:indexPath]; 
     // do something with this cell 
    } 
} 
+0

Obteniendo estos errores para indexPath.row ..... 1. Asignación para leer solo propiedad 2. Incremento para leer solo propiedad .... – iSeeker

+0

No debe haber creado una nueva variable local 'NSIndexPath'. Check indexPath no es el que se pasa a su función de fuente de datos de tabla o algo así. – darvids0n

4

(Esto se basa en aroths respuesta.)

me gusta definir esto como una categoría para UITableView para que esté disponible en todas partes.

(Como se ha mencionado un par de veces, usted debe estar seguro de que realmente desea iterar sobre las propias células. Por ejemplo: Lo utilizo para limpiar los UITableViewAccessoryCheckmark 's de todas las células antes de que al usuario seleccionado . celular Una buena regla de oro es para hacer esto sólo si los métodos de origen de datos no pueden hacer lo que necesita)

Definir como esto:.

- (void)enumerateCellsUsingBlock:(void (^)(UITableViewCell *cell))cellBlock { 
    NSParameterAssert(cellBlock != nil); 
    for (int section = 0; section < [self numberOfSections]; section++) { 
     for (int row = 0; row < [self numberOfRowsInSection:section]; row++) { 
      NSIndexPath *cellPath = [NSIndexPath indexPathForRow:row inSection:section]; 
      UITableViewCell *cell = [self cellForRowAtIndexPath:cellPath]; 
      if (cellBlock != nil) { 
       cellBlock(cell); 
      } 
     } 
    } 
} 

llamada así:

[self.tableView enumerateCellsUsingBlock:^(UITableViewCell *cell) { 
    NSLog(@"cell:%@", cell); 
}]; 

Sería un buen estilo para tipificar el bloque, también.

1

aún más simple y más elegante:

-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell 
             forRowAtIndexPath:(NSIndexPath *)indexPath { 
    // use the "cell" here 
} 

Pero, obviamente, no se ajusta a todas las situaciones.

0

Esta forma Im iteración en todas las células de la vista tabla ni siquiera las visibles, comprobar mi respuesta aquí:

https://stackoverflow.com/a/32626614/2715840

Consejo: código en Swift.

+0

Su solución en la versión OC, solo como referencia: [self.tableView scrollToRowAtIndexPath: indexPath atScrollPosition: UITableViewScrollPositionTop animated: NO]; – zaolian

Cuestiones relacionadas