我正在处理iOS应用程序的消息传递组件。我的UITableView _messageTable
上的每条消息都是一行。我在viewDidLoad
,viewWillAppear
和viewDidAppear
中尝试了以下代码(消息来自后台线程):
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;
}
答案 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];
}