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

时间:2015-01-26 20:26:23

标签: ios objective-c uitableview

我正在处理iOS应用程序的消息传递组件。我的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;
}

此代码有效,直到大约有20行。但是当有更多的消息时,它并没有完全滚动到底部。有某种限制吗?如果它意味着一直向下滚动,我的视图加载延迟就可以了。最终我将实现某种消息加载上限,但我想先了解并解决这个问题。

修改

这是视图控制器中的表视图。我在Message对象的数组属性中保存已发送和已接收的User个对象(消息对话另一端的人员。app.hero是用户已登录,继承自User对象)。没有意义的是,代码可以完美地处理大约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;
}

2 个答案:

答案 0 :(得分:2)

我已经确定这个问题与细胞高度有关。通过将tableView.estimatedRowHeight增加到44.0,表格视图可以完美地滚动到底部。但是,当消息在给定单元格中超出1行时仍存在问题。对于长度超过1行的每条消息,表格滚动会短几个像素。完全删除tableView.estimatedRowHeight似乎会导致类似于将其设置为44.0的行为。我想说我原来的问题已经回答了,但是我仍然不确定如何在多线细胞的可能性下完美地滚动它。

编辑 - 解决方案

实际上,通过移除UITableViewAutomaticDimension并在heightForRowAtIndexPath中手动计算高度来解决滚动错误的问题。

答案 1 :(得分:0)

这是一个适用于自动细胞高度测量的解决方案。这是一个很好的解决方法,但这似乎是一个Apple漏洞。

_manualScrolling=NO中设置viewDidLoad

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