如何在表格底部插入一行后正确地滚动表格视图?

4
这是我使用的代码:
//inserting a row at the bottom first
_numberOfRecords++;
[_tableView beginUpdates];
[_tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:_numberOfRecords-1 inSection:0]] withRowAnimation:UITableViewRowAnimationBottom];
[_tableView endUpdates];
//clear text
_inputField.text = @"";

//then scroll to bottom
CGPoint bottomOffset = CGPointMake(0, _tableView.contentSize.height + 44.0 + _tableView.contentInset.top - _tableView.bounds.size.height);
NSLog(@"%f", _tableView.contentSize.height + 44.0 + _tableView.contentInset.top - _tableView.bounds.size.height);
[_tableView setContentOffset:bottomOffset animated:YES];

这会以一种非常奇怪的方式滚动tableview。但是如果我将滚动代码放在插入之前,它就可以正常工作,只是它会忽略最新插入的行。也就是说,它会滚动到倒数第二行而不是滚动到最后一行(当然,因为它在插入新行之前滚动)。因此,我认为这段代码滚动到应该滚动到的位置没有问题。问题可能来自于向表视图插入行时违反了滚动表视图的动画。
我正在做一个聊天视图。每次用户发送或接收消息时,我都会将包含消息的行插入到表视图中,并将其滚动到底部。这就是为什么我在这里使用tableView。我尝试使用带有标签的scrollView,它可以正常工作,但是tableView在聊天视图中似乎更受欢迎。
我在考虑使用scrollView还是tableView,然后我发现苹果内置的信息应用程序使用的是tableView,所以我选择了tableView。如果scrollView与Label相比tableView更好,请告诉我。
无论如何,在插入新行后如何将tableView滚动到底部呢?

1
你不能使用 'scrollToRowAtIndexPath: atScrollPosition: animated:' 吗? - JeffN
2个回答

8
尝试使用UITableViewscrollToRowAtIndexPath:方法:
[self.tableView scrollToRowAtIndexPath: atScrollPosition: animated:];

这对我来说很好用。但是我看到有些人说 scrollToRowAtIndexPath 不能很好地处理页脚和节。 - Kyle Xie

1
这是我的解决方案:
[_tableView reloadData];

    //scroll to bottom
double y = _tableView.contentSize.height - _tableView.bounds.size.height;
CGPoint bottomOffset = CGPointMake(0, y);
NSLog(@"after = %f", y);
if (y > -_tableView.contentInset.top)
    [_tableView setContentOffset:bottomOffset animated:YES];

首先,在 endUpdates 后执行 reloadData。这可以确保在插入新行后更新 tableView 的 contentSize。然后检查滚动距离是否大于 contentInset.top(这是为了避免 tableview 被状态栏和导航栏遮挡)然后向下滚动,否则不滚动,因为会出现一些奇怪的动画。

或者,您可以简单地使用

[self.tableView scrollToRowAtIndexPath: inSection: atScrollPosition: animated:];

要滚动到您想要的行。但这并不能很好地处理带有节和页脚的单元格。对于普通的tableViewCell,您可以使用此代码来实现。否则,您可能会发现我的技巧解决方案表现更好。
无论如何,感谢您提供的所有答案。

beginUpdates和endUpdates有效地应用于表视图的更改,reloadData重新加载整个数据源。你必须使用其中之一,否则就没有意义。 - pronebird
如果显示的数据没有变化,则不要使用[_tableView reloadData],否则会导致性能问题。 - Ganesh G

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接