I’ve created a UITableview with sections that are clickable. When you click on them,
- they “expand” to reveal cells within them
- the clicked section scrolls to the top of the view.
I calculate all of the indexpaths to insert/delete the necessary cells and then insert them with the following code:
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:pathsToOpen withRowAnimation:insertAnimation];
[self.tableView deleteRowsAtIndexPaths:pathsToClose withRowAnimation:deleteAnimation];
[self.tableView endUpdates];
[self.tableView scrollToRowAtIndexPath:[pathsToOpen objectAtIndex:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
There’s only one problem- the sections below the selected section are hidden. The first screen-shot shows how the tableview should look. The second screen-shot shows how it actually looks.

If you scroll up (so the hidden sections are offscreen) and then scroll back down, the hidden sections are brought back (once again visible). My guess as to why this is happening is the following:
The insert/delete animations are happening at the same time as the scrollToRowAtIndexPath and it is confusing the TableView. If I hadn’t done scrollToRowAtIndexPath sections 3 & 4 would have been offscreen – and so the tableView somehow still thinks they are offscreen. UITableview hides cells/sections that are offscreen as an optimization. If I call scrollToRowAtIndexPath with a dispatch_after with 2 seconds, then sections 3 & 4 are displayed correctly.
So I think I know why this is happening, but I don’t know how to fix/override this UITableview optimization. Actually, if I implement scrollViewDidEndScrollingAnimation and then add a breakpoint in this function, the app displays sections 3 & 4 correctly (that’s how I got the first screen-shot). But once continuing from this function, the cells disappear.
The full project can be downloaded here
Additional implementation details: Sections are legitimate UITableView sections. I’ve added a tapGestureRecognizer that triggers a delegate callback to the tableview. Included below is the entire method that opens the sections.
- (void)sectionHeaderView:(SectionHeaderView *)sectionHeaderView sectionOpened:(NSInteger)sectionOpened
{
// Open
sectionHeaderView.numRows = DefaultNumRows;
sectionHeaderView.selected = YES;
NSMutableArray *pathsToOpen = [[NSMutableArray alloc] init];
for (int i = 0; i < sectionHeaderView.numRows; i++)
{
NSIndexPath *pathToOpen = [NSIndexPath indexPathForRow:i inSection:sectionOpened];
[pathsToOpen addObject:pathToOpen];
}
// Close
NSMutableArray *pathsToClose = [[NSMutableArray alloc] init];
if (openSectionHeader)
{
for (int i = 0; i < openSectionHeader.numRows; i++)
{
NSIndexPath *pathToClose = [NSIndexPath indexPathForRow:i inSection:openSectionHeader.section];
[pathsToClose addObject:pathToClose];
}
}
// Set Correct Animation if section's already open
UITableViewRowAnimation insertAnimation = UITableViewRowAnimationBottom;
UITableViewRowAnimation deleteAnimation = UITableViewRowAnimationTop;
if (!openSectionHeader || sectionOpened < openSectionHeader.section)
{
insertAnimation = UITableViewRowAnimationTop;
deleteAnimation = UITableViewRowAnimationBottom;
}
openSectionHeader.numRows = 0;
openSectionHeader.selected = NO;
openSectionHeader = sectionHeaderView;
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:pathsToOpen withRowAnimation:insertAnimation];
[self.tableView deleteRowsAtIndexPaths:pathsToClose withRowAnimation:deleteAnimation];
[self.tableView endUpdates];
[self.tableView scrollToRowAtIndexPath:[pathsToOpen objectAtIndex:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
From what I can tell, the problem is occurring when returning a section view that’s already been used. Instead of:
I get no problem if I create a new view each time:
It’s possible this is occurring because you’re using
[self.tableView dequeueReusableCellWithIdentifier:SectionHeaderView_NibName];to create section headers and hold on to them in an array, which I don’t think UITableViewCell was created for, but I’m not certain. You may want to consider foregoing UITableViewCell for section views and instead use something else (perhaps a UIImageView with a UILabel). Or you can just not store the Section Views in an array…the way you currently have your code set up, you don’t need the array and creating a new view is trivial enough you don’t need to worry about it.