Q:
场景是,数据回来,[self.tableView reloadData] 时,想让他回到列表顶部;之前没注意过这个问题,今天发现 reloadData 时候,用 scrollToTop,或者 setContentOffset 并没有生效。最后解决办法如下。建议尽量用方案1-1,1-2;
A:
方案1-1:
这种方法,仅适用于 tableView 没有设置 tableHeaderView 的情况。animated 可自行选择 YES/NO,reloadData 放前面也行,放后面也行,为所以为。
不过这里得注意判断这里的 section:0 是不是有 cell,也就是下面这个 if()。如果根本就没cell,却还要 scrollTo 的话,那就蹦萨卡拉卡了
UITableViewScrollPositionTop 意思是把指定 indexPath 的 cell 放到屏幕最顶上,所以会导致 header 被顶上去盖住。
[self.tableView reloadData];
if ([self.tableView numberOfRowsInSection:0]) {
NSIndexPath *indexPathOne = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView scrollToRowAtIndexPath:indexPathOne atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
方案1-2:
这种适用于有 tableHeaderView,但是 header 不太高的情况,UITableViewScrollPositionMiddle 意思是把指定 indexPath 的 cell 放到屏幕中央,所以会把 cell 尽量往下拉,就可以正常展示出 header。
[self.tableView reloadData];
if ([self.tableView numberOfRowsInSection:0]) {
NSIndexPath *indexPathOne = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView scrollToRowAtIndexPath:indexPathOne atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}
方案2:
这种方法比较通用,有没有 tableHeaderView 都可以,不过缺点是这里的 animated 一定要为 NO,否则某些情况下不生效。
[UIView animateWithDuration:0 animations:^{
[self.tableView setContentOffset:CGPointZero animated:NO];
} completion:^(BOOL finished) {
[self.tableView reloadData];
}];
⚠️WARRING:
方案2 有一个隐藏问题。回滚到最前面时,你的 tableView 会加载前面的cell,这时候会调用 cellForRowAtIndexPath,以及 heightForRowAtIndexPath 等代理方法;但是在这之前,你可能已经删掉了 dataSource 里的数据,或者更换了 dataSource 里的数据,那么从 dataSource 数组取值时候,很可能会出现数组越界现象。
所以,建议一定要加好数组越界的判定处理啊!!!