iPad: Iterate over every cell in a UITableView?
Assuming a variable myTableView
exists and its delegate and data source are both set:
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
}
}
To iterate over every visible cell in a UITableView:
for (UITableViewCell *cell in self.tableView.visibleCells) {
NSIndexPath *cellIndexPath = [self.tableView indexPathForCell:cell];
(edited to better state answer and hope that this is indexed more accurately for search results with the intention of saving others more time in the future)
Even simpler and more elegant:
-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath {
// use the "cell" here
}
But obviously it doesn't fit all situations.
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'
}
}
Swift 4:
for section in 0...self.tableView.numberOfSections - 1 {
for row in 0...self.tableView.numberOfRows(inSection: section) - 1 {
let cell = self.tableView.cellForRow(at: NSIndexPath(row: row, section: section) as IndexPath)
print("Section: \(section) Row: \(row)")
}
}
by steve Iterate over all the UITableCells given a section id
(This builds on aroths answer.)
I like to define this as a category to UITableView
so it's available everywhere.
(As mentioned a few times, you should be sure you really want to iterate over the cells themselves. For example: I use this to clear the UITableViewAccessoryCheckmark
's from all the cells before setting it to the user selected cell. A good rule of thumb is to do this only if the datasource methods can't do what you need to.)
Define like this:
- (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);
}
}
}
}
Call like this:
[self.tableView enumerateCellsUsingBlock:^(UITableViewCell *cell) {
NSLog(@"cell:%@", cell);
}];
It would be good style to typedef the block, too.