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

iOS-UITableView不会滚动到数据源中的最后一行,ios,objective-c,uitableview,Ios,Objective C,Uitableview,我正在开发iOS应用程序的消息传递组件。每条消息都是我的UITableView\u messageTable上的一行我在viewDidLoad、viewwillbeen和viewdidbeen中尝试了以下代码(消息来自后台线程): 这段代码一直工作到大约有20行。但是当有更多的消息时,它不会一直滚动到底部。有什么限制吗?如果视图加载延迟意味着一直滚动到底部,我可以接受。最终,我将实现某种消息加载上限,但我想首先理解并解决这个问题 编辑 这是视图控制器中的表视图。我正在将发送和接收的消息对象保存在

我正在开发iOS应用程序的消息传递组件。每条消息都是我的
UITableView\u messageTable上的一行
我在
viewDidLoad
viewwillbeen
viewdidbeen
中尝试了以下代码(消息来自后台线程):

这段代码一直工作到大约有20行。但是当有更多的消息时,它不会一直滚动到底部。有什么限制吗?如果视图加载延迟意味着一直滚动到底部,我可以接受。最终,我将实现某种消息加载上限,但我想首先理解并解决这个问题

编辑

这是视图控制器中的表视图。我正在将发送和接收的
消息
对象保存在
用户
对象的数组属性中(消息对话另一端的人。
app.hero
是登录的用户,从
用户
对象继承)。没有意义的是,该代码可以完美地处理多达20条消息。除此之外,它不会一直滚动,但我仍然可以按预期手动滚动到底部。单元格配置代码的其余部分为:

- (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;
}

我已经确定这个问题与单元格高度有关。通过将
tableView.estimatedRowHeight
增加到44.0,表格视图将完美地滚动到底部。但是,当消息在给定单元格中包装超过1行时,仍然存在一个问题。对于每一条长度超过一行的消息,表格滚动条会短几个像素。删除tableView.estimatedRowHeight似乎会产生与将其设置为44.0类似的行为。我想说我最初的问题得到了回答,但考虑到多行单元格的可能性,我仍然不确定如何使其完美滚动

编辑-解决方案


实际上,通过删除
UITableViewAutomaticDimension
并在
heightForRowAtIndexPath
中手动计算高度,可以解决不正确滚动的问题

这里有一个解决方案,可以很好地自动调整单元格高度。这是一个相当好的解决办法,但这似乎是一个苹果的错误

viewDidLoad
中设置
\u手动滚动=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];
}

我看你现在的作品没有任何问题。请您提供更多的代码,特别是关于如何更新
\u privateMessages
?这可能是多线程问题。这是表视图控制器还是具有表视图的视图控制器?如果是后者,请确保表格视图没有离开屏幕底部。您是否动态设置单元格高度?那么,当您尝试手动向下滚动到隐藏行时会发生什么?所有,感谢您的注释,我已编辑了问题并提供了更多信息。我回忆起我曾经遇到过这个问题,它需要一些仔细的检查,以确保单元格本身和请求它的接口之间的行高度一致(您可能需要做的是将单元格高度存储在数据源中,这样您就可以始终在
heightForRow…
中返回准确的值)(请确保实现
高度FORROW
.IIRC,如果您的单元格不都是标准高度,则需要该高度。)@HotLicks-让我看看我是否理解你的建议。使用
heightForRowAtIndexPath
而不是
UITableViewAutomaticDimension
手动计算行高。然后存储每个高度,并使用类似
[\u messageTable setContentOffset:bottomOffset动画:YES]
其中
bottomOffset
是通过对存储的所有行高值求和来计算的?根据创建单元格的方式计算行高,并将其返回到
heightForRow…
(而不是
estimatedroweight
)委托方法。这可以确保表视图具有准确的行高编号,然后
scrollToRow…
应该可以工作。(顺便说一句,您不应该在每次调用
cellForRow
时都设置tableView.estimatedRowHeight和tableView.rowHeight。在设置过程中,您只能设置一次(如果全部设置的话)
-(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];
}