Skip to content

Instantly share code, notes, and snippets.

@kristopherjohnson
Last active January 16, 2020 18:59
Show Gist options
  • Save kristopherjohnson/f18fb872ace42707c426 to your computer and use it in GitHub Desktop.
Save kristopherjohnson/f18fb872ace42707c426 to your computer and use it in GitHub Desktop.
Update visible cells from a UITableViewController without calling -[UITableView reloadData]
- (void)reconfigureVisibleCells
{
NSInteger sectionCount = [self numberOfSectionsInTableView:self.tableView];
for (NSInteger section = 0; section < sectionCount; ++section) {
NSInteger rowCount = [self tableView:self.tableView numberOfRowsInSection:section];
for (NSInteger row = 0; row < rowCount; ++row) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell != nil) {
[self configureCell:cell forRowAtIndexPath:indexPath];
}
}
}
}
// Cell configuration code, shared by -tableView:cellForRowAtIndexPath: and reconfigureVisibleCells
- (void)configureCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
// ...
}
@stianhoiland
Copy link

What about using UITableView's indexPathsForVisibleRows:

for (NSIndexPath *indexPathForVisibleRow in self.tableView.indexPathsForVisibleRows) {
        UITableViewCell *visibleCell = [self.tableView cellForRowAtIndexPath:indexPathForVisibleRow];
        if (visibleCell != nil) {
            [self configureCell:visibleCell forRowAtIndexPath:indexPathForVisibleRow];
        }
}

I also suggest changing the signature of -configureCell:forRowAtIndexPath: to:

- (void)tableView:(UITableView *)tableView configureCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;

Then you get:

- (void)configureVisibleCellsForTableView:(UITableView *)tableView {
    for (NSIndexPath *indexPathForVisibleRow in tableView.indexPathsForVisibleRows) {
        UITableViewCell *visibleCell = [self.tableView cellForRowAtIndexPath:indexPathForVisibleRow];
        if (visibleCell != nil) {
            [self tableView:tableView configureCell:visibleCell forRowAtIndexPath:indexPathForVisibleRow];
        }
    }
}

I also think it's safe to remove if (visibleCell != nil), since we are explicitly asking the table view for the visible rows, but I kept it in case, for some (possibly non-existent) reason, no cell has been allocated for that row.

@stianhoiland
Copy link

Here's how I do it:

- (void)configureVisibleCellsForTableView:(UITableView *)tableView animated:(BOOL)animated {
    [self tableView:tableView configureRowsAtIndexPaths:tableView.indexPathsForVisibleRows animated:animated];
}

- (void)tableView:(UITableView *)tableView configureRowsAtIndexPaths:(NSArray *)indexPaths animated:(BOOL)animated {
    for (NSIndexPath *indexPath in indexPaths) {
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        if (cell) {
            [self tableView:tableView configureCell:cell forRowAtIndexPath:indexPath animated:animated];
        }
    }
}

- (void)tableView:(UITableView *)tableView configureCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated {
    // Cell configuration
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment