layoutIfNeeded使用-解决scrollToRowAt
最近开发遇到了两个问题,原因全是控件UI数据没有及时刷新导致的,最后的解决方案都是使用layoutIfNeeded
解决。
第一个问题
[self.dataArray insertObjects:detailList atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, detailList.count)]];
[self.mainTableView reloadData];
[self.mainTableView layoutIfNeeded];
if ([self.TRADESEQ isEqualToString:@""]) {
[self.mainTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:(detailList.count - 1) >= 0 ? (detailList.count - 1) : 0 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:NO];
}else{
[self.mainTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:detailList.count + 1 inSection:0] atScrollPosition:UITableViewScrollPositionNone animated:NO];
}
本来想调用scrollToRowAtIndexPath
方法在请求完数据时,使TableView
滚动到新数据的底部,但是第一次加载时显示正常,这个TableView
定位到最底部,但是在加载更多时,会出现滚动位置错位的问题。这个需要在scrollToRowAtIndexPath
方法前调用layoutIfNeeded
原理:引用自https://www.cnblogs.com/LynnAIQ/p/5915117.html
如果在reloadData后需要立即获取tableview的cell、高度,或者需要滚动tableview,那么,直接在reloadData后执行代码是有可能出问题的。
reloadDate并不会等待tableview更新结束后才返回,而是立即返回,然后去计算表高度,获取cell等。
如果表中的数据非常大,在一个run loop周期没执行完,这时,需要tableview视图数据的操作就会出问题了。
apple并没有直接提供reloadData的api,想要程序延迟到reloadData结束在操作,可以用以下方法:
方法一:
[self.tableView reloadData];
[self.tableView layoutIfNeeded];
//刷新完成
方法二:
[self.tableView reloadData];
dispatch_async(dispatch_get_main_queue(), ^{
//刷新完成
});
reloadDate会在主队列执行,而dispatch_get_main_queue会等待机会,直到主队列空闲才执行。
类似函数:
- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;
- (void)scrollToNearestSelectedRowAtScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;
- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated; // animate at constant velocity to new offset
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated;
当使用[tableView reloadData];刷新数据时,不能直接在后面使用上面的函数。reload
第二个问题
第二个问题简单描述就是xib
加载的View
在获取其中控件的frame
是值不对,获取到的frame
不是根据不同机型约束设置后显示出来的frame
,而是在Xib
中显示的原始大小。甚至在viewWillAppear
方法中获取也是原始大小。
解决方案也是在获取frame
前调用layoutIfNeeded
方法