今天开发 崩溃 报错:
[UITableView _contentOffsetForScrollingToRowAtIndexPath:atScrollPosition:]:row (x) beyond bounds...
原因:
执行
[UITableView reloadDate]
或者其他刷新 UITableView 的方法;
Cell 计算量 数据量比较大的情况下,在一个run loop周期没执行完;
UITableView 会可能在数据还没加载完就立即去执行
数据源-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section方法。
可能会有崩溃情况。
解决方法:
逻辑:把数据加载放回主线程,先保证数据加载完整了再执行数据源的代理方法。
方法一:
等待线程完成
//1.先让 reloadDate 在主队列执行
[tableView reloadData];
//2.dispatch_get_main_queue会等待机会,直到主队列空闲,也就是数据加载完毕才继续执行。
dispatch_async(dispatch_get_main_queue(), ^{
//刷新完成 / 各种操作
//我之前崩溃就是这个刷新 会有崩溃 置入 这里就没有崩溃情况
[tableView reloadSections:[[NSIndexSet alloc] initWithIndex:section] withRowAnimation:UITableViewRowAnimationAutomatic];
});
方法二:
进行重绘
[tableView reloadData];
// 强制重绘并等待完成
[tableView layoutIfNeeded];
//我之前崩溃就是这个刷新 会有崩溃 置入 这里就没有崩溃情况
[tableView reloadSections:[[NSIndexSet alloc] initWithIndex:section] withRowAnimation:UITableViewRowAnimationAutomatic];
推荐!(新增)方法三:
逻辑:判断 UITableView 是否加载完成(是否存在), 完成后再继续下一步
-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath )indexPath
{
//用于判断tableview当前是否加载完成
if([indexPath row] == ((NSIndexPath)[[_mainTableView indexPathsForVisibleRows] lastObject]).row){
//加载已结束 表示已存在
dispatch_async(dispatch_get_main_queue(),^{
//dispatch_get_main_queue会等待机会,直到主队列空闲,也就是数据加载完毕才继续执行。
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
/*
刷新 、定位 等操作 可以置入这里。
也可以提取方法到外面去,会灵活点。
这个主要是判断存在与否 [indexPath row] == ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row
*/
});
}
}
以上三个方法,个人推荐第三个方法。