UITableView滚动到底部时崩溃的解决方法

项目中的直播界面,要求客户端发送信息后,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

你可能感兴趣的:(UITableView滚动到底部时崩溃的解决方法)