简体   繁体   English

iOS-UITableView不会滚动到数据源中的最后一行

[英]iOS - UITableView Does Not Scroll To Last Row In Data Source

I'm working on a messaging component of an iOS application. 我正在研究iOS应用程序的消息传递组件。 Each message is a row on my UITableView _messageTable I tried the following code in viewDidLoad , viewWillAppear and in viewDidAppear (messages are coming in from a background thread): 每条消息都是我的UITableView _messageTable上的一行,我在viewDidLoadviewWillAppearviewDidAppear尝试了以下代码(消息来自后台线程):

dispatch_async(dispatch_get_main_queue(), ^{
    [_messageTable reloadData];
});
dispatch_async(dispatch_get_main_queue(), ^{
    [self scrollToBottomOfTable];
});

-(void)scrollToBottomOfTable {
    NSInteger rowCount = [_messageTable numberOfRowsInSection:0];
    if (rowCount > 0) {
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow: rowCount-1 inSection: 0];
        [_messageTable scrollToRowAtIndexPath: indexPath atScrollPosition: UITableViewScrollPositionBottom animated: YES];
    }
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return _privateMessages.count;
}

This code works until there are about 20 or so rows. 直到大约20行左右,此代码才有效。 But when there are more messages, then it doesn't quite scroll all the way to the bottom. 但是,当有更多消息时,它并不会一直滚动到底部。 Is there some sort of limit? 有某种限制吗? I'm ok with a view load delay if it means scrolling all the way to the bottom. 我同意视图加载延迟,如果这意味着一直滚动到底部。 Eventually I will implement some sort of message loading cap, but I would like to first understand and solve this issue. 最终,我将实现某种消息加载上限,但我想首先了解并解决此问题。

EDIT 编辑

This is a table view within a view controller. 这是视图控制器中的表视图。 I'm saving sent and received Message objects in a User object's array property (the person on the other end of the message conversation. app.hero is the user that is logged in, inheriting form the User object). 我将已发送和已接收的Message对象保存在User对象的array属性中(消息对话另一端的人app.hero是登录的User ,继承自User对象)。 The thing that doesn't make sense is that the code works perfectly for up to around 20 messages. 没有意义的是,该代码可以完美地处理多达20条消息。 Beyond that, it doesn't scroll all the way, but I can still manually scroll to the bottom as expected. 除此之外,它不会一直滚动,但是我仍然可以按预期手动滚动到底部。 The rest of the cell config code is : 其余的单元格配置代码为:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
tableView.estimatedRowHeight = 20.0;
tableView.rowHeight = UITableViewAutomaticDimension;
Message *message = [_privateMessages objectAtIndex:indexPath.row];
static NSString *cellId = @"messageCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
    cell.textLabel.numberOfLines=0;
}
return [self configureTableCell:cell forMessage:message];
}

- (UITableViewCell *)configureTableCell:(UITableViewCell *)cell forMessage:(Message *)message {
AppDelegate *app = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if (message.sender == app.hero) {
    cell.backgroundColor = [UIColor whiteColor];
    cell.textLabel.textAlignment = NSTextAlignmentRight;
} else {
    cell.backgroundColor = [UIColor colorWithRed:0 green:1 blue:0.2 alpha:0.3];
    cell.textLabel.backgroundColor = [UIColor colorWithWhite:0 alpha:0];
    cell.textLabel.textAlignment = NSTextAlignmentLeft;
}
cell.textLabel.text = message.content;
return cell;
}

I've determined that this issue has to do with cell height. 我确定此问题与单元格高度有关。 By increasing tableView.estimatedRowHeight to 44.0, the table view scrolls flawlessly to the bottom. 通过将tableView.estimatedRowHeight增加到44.0,表格视图可以完美地滚动到底部。 However, there remains an issue with when messages wrap beyond 1 line in a given cell. 但是,当消息在给定单元格中换行超过1行时,仍然存在问题。 For each message longer than 1 line, the table scroll comes up a few more pixels short. 对于每条超过1行的消息,表格滚动条会再短几个像素。 Removing tableView.estimatedRowHeight altogether seems to result in similar behavior as setting it to say, 44.0. 完全删除tableView.estimatedRowHeight似乎会产生与将其设置为44.0相似的行为。 I want to say my original question is answered, but I'm still not sure how to make it scroll perfectly given the likelihood of multi-line cells. 我想说我的原始问题已经回答,但是鉴于多行单元格的可能性,我仍然不确定如何使其完美滚动。

EDIT - SOLUTION 编辑-解决方案

The problem of incorrect scrolling is in fact solved by removing UITableViewAutomaticDimension and manually calculating the height in heightForRowAtIndexPath . 实际上,通过删除UITableViewAutomaticDimension并手动计算heightForRowAtIndexPath的高度,可以解决滚动不正确的问题。

Here is a solution that works well with auto cell height sizing. 这是一种适用于自动像元高度调整的解决方案。 It's quite a workaround, but this appears to be an Apple bug. 这是一个解决方法,但这似乎是Apple的错误。

Set _manualScrolling=NO in viewDidLoad . viewDidLoad设置_manualScrolling=NO

-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
    if (!decelerate) {
        _manualScrolling = NO;
    } else {
        _manualScrolling = YES;
    }
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    _manualScrolling = YES;
}

-(void)reloadTable {
    dispatch_async(dispatch_get_main_queue(), ^{
        [_messageTable reloadData];
    });
    dispatch_async(dispatch_get_main_queue(), ^{
        [self scrollToBottomOfTable];
    });
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (!_manualScrolling && ![self scrolledToBottom]) {
        [self scrollToBottomOfTable];
    }
}

-(BOOL)scrolledToBottom {
    NSInteger rowCount = [_messageTable numberOfRowsInSection:0];
    NSArray *visibleIndices = [_messageTable indexPathsForVisibleRows];
    NSIndexPath *lastVisibleIndex = [visibleIndices lastObject];
    NSIndexPath *lastIndex = [NSIndexPath indexPathForRow: rowCount-1 inSection: 0];
    return lastVisibleIndex.row == lastIndex.row;
}

-(void)scrollToBottomOfTable {
    NSInteger rowCount = [_messageTable numberOfRowsInSection:0];
    if (!rowCount > 0) return;
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow: rowCount-1 inSection: 0];
        [_messageTable scrollToRowAtIndexPath: indexPath atScrollPosition: UITableViewScrollPositionBottom animated: YES];
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM