10

I have a potentially very long scrolling log of messages within a UITableView The user would be able to navigate the table by scrolling.

What I'm trying to do is add new content at the top of the table. If the top of the table is visible, the new row would push the rest of the content down. But if the first row of the table is not visible, the table would silently add another row on top without scrolling.

I'm doing this to prevent the table scrolling to the top from interrupting the user browsing data. If I ask the table to simply scroll to the new insertion point, the user's position within the table would be lost, frustrating the user.

One of the ways I can try to implement this is by inserting data into an NSMutableArray at index 0. Would this work? An extra question: how expensive is inserting data at the beginning of an NSMutableArray. I would expect that such operation is optimized, but would like to make sure. What am I missing with this implementation?

Thank you!

Alex Stone
  • 46,408
  • 55
  • 231
  • 407
  • possible duplicate of [Keep uitableview static when inserting rows at the top](http://stackoverflow.com/questions/4279730/keep-uitableview-static-when-inserting-rows-at-the-top) – BB9z Dec 17 '14 at 02:50

3 Answers3

13

How to insert without bumping the view:

  • Use the tableView's (UIScrollView) contentOffset values to find where the user is currently scrolled to.
  • Add the new row at the top, with animated:NO
  • Update the tableView's contentOffset to be where the user was at plus whatever the height of your row is.

How to avoid causing issues doing this while the user is dragging:

  • Keep track of when the user is dragging, and if you want to insert rows during a drag / motion, add them to a queue that is executed after the user releases.
Tim
  • 14,447
  • 6
  • 40
  • 63
  • 1
    Something tells me that this has to be surrounded with [tableView beginUpdates] and [tableView endUpdates] to work seamlessly. Am I correct? – Alex Stone Nov 05 '11 at 19:50
  • I don't believe so, though I haven't even used those methods. Try it without and see what happens. – Tim Nov 06 '11 at 00:29
  • 1
    Instead of using InsertCell, you add the cell's height to your saved offset. At the end, reloadData and update to the saved offset. See also: http://stackoverflow.com/questions/4279730/keep-uitableview-static-when-inserting-rows-at-the-top/9121544#9121544 – Walt Sellers Feb 02 '12 at 23:52
  • I tried the same logic above but isn't working. I am using autolayout. Also, the above logic wont work if the content inset changes after reload data. Like in a chat application. – GoGreen Jan 21 '16 at 13:48
6
CGSize beforeContentSize = self.tableView.contentSize;
[self.tableView reloadData];
CGSize afterContentSize = self.tableView.contentSize;
            
CGPoint afterContentOffset = self.tableView.contentOffset;
CGPoint newContentOffset = CGPointMake(afterContentOffset.x, afterContentOffset.y + afterContentSize.height - beforeContentSize.height);
self.tableView.contentOffset = newContentOffset;
Ganpat
  • 768
  • 3
  • 15
  • 30
nahlamortada
  • 489
  • 6
  • 16
2

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