David David - 1 year ago 198
iOS Question

UITableView scroll to the bottom messed up with EstimatedRowHeight

I'm trying to scroll to the bottom of my UITableView (commentsFeed) whenever the user creates a new comment or the user refreshes the UITableView.

The code I use is:

func scrollToBottomOfComments() {

var lastRowNumber = commentsFeed.numberOfRowsInSection(0) - 1
var indexPath = NSIndexPath(forRow: lastRowNumber, inSection: 0)
commentsFeed.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: true)

The problem is here in

commentsFeed.rowHeight = UITableViewAutomaticDimension
commentsFeed.estimatedRowHeight = 150

This basically states that the comments can have dynamic heights because users could post either really long comments or really short comments.

When I use the estimatedRowHeight, my
doesn't properly scroll to the bottom because it basically assumes my table height is
commentsFeed.count * commentsFeed.estimatedRowHeight

This isn't correct though.

When I remove the
though, it doesn't seem to work either, and I think the reason is because it doesn't have the row height calculated properly because the rows each have dynamic heights.

How do I mitigate this?

Edit: It should be stated that the scroll doesn't end up at the right position, but the moment I use my finger to scroll anywhere, then the data jumps into place where it should have been via the scroll

Answer Source

Why don't you calculate the real size of row by something similar to below method.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    CustomObject *message = [list.fetchedObjects objectAtIndex:indexPath.row];

    //fontChat not available yet

    NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:message];
    NSRange all = NSMakeRange(0, text.length);

    [text addAttribute:NSFontAttributeName value:[UIFont fontWithName:DEFAULT_FONT size:21] range:all];
    [text addAttribute:NSForegroundColorAttributeName value:RGB(61, 61, 61) range:all];

    CGSize theSize = [text boundingRectWithSize:CGSizeMake(200, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;

    if (theSize.height == 0) {
        theSize.height = FIXED_SIZE;

    return theSize.height;

Now for scrolling, I use the following source: Check it out.

-(void) scrollTolastRow
    if (self.tableView.contentSize.height > self.tableView.frame.size.height)
        CGPoint offset = CGPointMake(0, self.tableView.contentSize.height - self.tableView.frame.size.height);
        [self.tableView setContentOffset:offset animated:YES];