项目中的直播界面,要求客户端发送信息后,tableView自动滚动到最后一行.
UITableView中有滚动的方法:
- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated
上述方法tableView会调用数据源中的
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
在数据源方法中,tableView会创建所有的UITableViewCell.一般编码思路是:每当有人提问就调用[tableView reload]方法,并让其滚动到底部.但是会出现错误:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '-[UITableView _contentOffsetForScrollingToRowAtIndexPath:atScrollPosition:]: row (14) beyond bounds (14) for section (0).'
究其原因,是tableView在创建cell的数据源方法还未完成时,已经在调用numberOfRows的数据源方法了.
假如第一次reloadData时,需要创建10个Cell;
当在创建第10个cell时,又走了reloadData方法,要求创建8个Cell;
上述情况出现时,就会上面的错误.
根据错误原因,可以通过设置UITableView的contentSize属性来解决. 下面是我模仿上述情景写的一个Demo:
- (void)viewDidLoad {
[super viewDidLoad];
self.arrM = [NSMutableArray arrayWithObjects:@"1",@"2", nil];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(itemClick)];
}
for (int i = 0; i < 100; i++) {
NSLog(@"%.0f", self.tableView.contentSize.height);
NSLog(@"%@", NSStringFromCGPoint(self.tableView.contentOffset));
dispatch_async(dispatch_queue_create("a", DISPATCH_QUEUE_CONCURRENT), ^{
NSLog(@"%@",[NSThread currentThread]);
NSMutableArray *arrM_new = [NSMutableArray arrayWithArray:self.arrM];
[arrM_new addObject:@"1"];
if (arrM_new.count > 30) {
[arrM_new removeObjectsInRange:NSMakeRange(0, 29)];
}
self.arrM = arrM_new;
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
NSLog(@"%.0f", self.tableView.contentSize.height);
CGPoint offset = CGPointMake(0,self.tableView.contentSize.height - self.tableView.frame.size.height);
if (offset.y < 0) {
offset = CGPointMake(0, -44);
}
[self.tableView setContentOffset:offset animated:NO];
});
});
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.arrM.count;
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
}
cell.textLabel.text = [NSString stringWithFormat:@"%zd组%zd行",indexPath.section,indexPath.row];
return cell;
}
- (BOOL)prefersStatusBarHidden{
return YES;
}
源码地址:
https://github.com/zhudong10/ZDZhiBoTableView.git