UITableView指定cell刷新问题调研(环境xcode9+IOS10、11)
一般UITableView需要刷新的时候调用reloadData即可刷新整个列表。但这么刷新,首先性能并不高,其次在一些特殊场景下,也无法达到效果。所以有时候需要仅仅刷新某几行的cell,某个section的全部cell,或者仅仅是刷新某一行cell。这时候需要调用:
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
这类API其实有个要求的,操作之前的cell和操作之后的cell 不能是同一个cell。 官方文档是这么说的:

意思是reloadRowsAtIndexPaths会调用data source,为这一行重新创建一个全新的cell,然后根据动画替换旧的cell。类似下面这种复用cell的写法不会有任何问题。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
switch (indexPath.row) {
static NSString *ideitifier = @"tgCell";
TgCell *cell = [tableViewdequeueReusableCellWithIdentifier:ideitifier];
if (!cell) {
cell = [[TgCell alloc] initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:ideitifier];
// do something
}
return cell;
}
如果是返回固定的cell,类似下面的写法,就会出现问题。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.row == 0){
return self.firstCell;
}
}
这时候用reloadRowsAtIndexPaths刷新row=0的时候,调用data source得到的是同一个cell,指向同一个内存空间。会发生一些不可预见的问题:根据animation参数的不同。
UITableViewRowAnimationNone 没有动画的情况,cell有可能不刷新,或出现空白区域
UITableViewRowAnimationRight 有动画的情况,cell会有消失动画,然后不再显示。刷新的话会重新出现。
reloadData 和 reloadRowsAtIndexPaths 需要注意的区别:reloadRowsAtIndexPaths执行过程中,需要 'blends' 旧cell 和 新cell,就是同时需要这两个cell,如果两个cell是指向同一个,就会出现问题。或者有一个是nil,也会出现surprise!stockflow相关回答

另外发现一个: reloadRowsAtIndexPaths 一个cell的时候,会把相关的其他的cell状态刷新成正确的。所以一直没发现项目中的一个隐患。刷新一组cell,最后一个cell是复用的,所以会使得所有的cell都被正常刷新,没有问题。
ps.有的时候仅仅是高度问题,想刷新cell的高度,网上很多人都这么用:

貌似是没什么问题,能达到效果。 但是官方api是明确说了,这样做可能会出现问题。所以这样做是有隐患的。

网友评论