0

I want to add rows to a table view without the visible cells being moved, similarly to Twitter for iPhone, Tweetbot and several others. Every method I have tried thus far accomplishes that eventually, but does funky animations in between. Here is the current solution, which moves cells around but eventually ends up staying in the same place.

- (void)controllerDidChangeContent:(NSFetchedResultsController*)controller
{
    UITableViewCell *referenceCell;
    if ([self.tableView.visibleCells count] > 0) {
        referenceCell = [self.tableView.visibleCells lastObject];
    }
    CGFloat offset = referenceCell.frame.origin.y - self.tableView.contentOffset.y;

    [self.tableView endUpdates];

    [self.tableView setContentOffset:CGPointMake(0.0, referenceCell.frame.origin.y - offset) animated:NO];
}
David Beck
  • 10,099
  • 5
  • 51
  • 88
  • It's important to note that if I remove the endUpdates (and related table update code) and replace it with a complete table refresh, it does work. However, that is not very efficient. – David Beck Nov 06 '11 at 00:26

3 Answers3

1

Try this:

  1. Record the offset to the first visible cell just as before
  2. Make sure that UITableView dataSource already contains data for new items.
  3. Call -insertRowsAtIndexPaths:withRowAnimation: on the UITableView with UITableViewRowAnimationNone. You can specify all index paths that you want to insert in one go. The number of inserted rows must match the number of new items.
  4. Call -setContentOffset: just as before

Avoid calling -beginUpdates and -endUpdates on the table view. -endUpdates causes animations to be done for the original cells.

It seems that insertRowsAtIndexPaths alone may animate cells. You could try a workaround like this:

for (UITableViewCell *cell in [tableView visibleCells])
{
  [cell.layer removeAllAnimations];
}
zoverf
  • 29
  • 2
0

Could you just reload the data source, and immediately call

[tableview selectRowAtIndexPath: animated:NO scrollPosition:<#(UITableViewScrollPosition)#>];

You would probably need to get the current position which you could do with

[[tableview indexPathsForVisibleRows] objectAtIndex:0];

I haven't tested this out though, so I'm not 100% on it.

Amit Shah
  • 4,176
  • 2
  • 22
  • 26
  • Even if that did work, it would only get it in the ballpark, the cell would not be in the exact same spot. Also, it doesn't work. – David Beck Nov 06 '11 at 00:25
0

Just posted an answer with code snippets here

Keep uitableview static when inserting rows at the top

Basically:

  • Save the scroll offset where you would have called beginUpdate:.
  • In place of calls to InsertCell you add the cell's height to the saved offset.
  • Where you would have called endUpdate:, call reloadData, then scroll by the saved offset with NO animation.
Community
  • 1
  • 1
Walt Sellers
  • 3,806
  • 30
  • 35