当调用reloadRowsAtIndexPaths时,UITableView弹回到一节的顶部

当用户点击我的行中的一个button时,我正在更新该行的基础模型,然后为给定行(即单行重新加载)调用reloadRowsAtIndexPaths。

- (IBAction)handleCompleteTouchEvent:(UIButton *)sender { NSIndexPath *indexPath = [self.tableView indexPathForView:sender]; id item = [self dataForIndexPath:indexPath]; if ([item respondsToSelector:@selector(completed)]) { // toogle completed value BOOL completed = ![[item valueForKey:@"completed"] boolValue]; [item setValue:[NSNumber numberWithBool:completed] forKey:@"completed"]; [self.tableView beginUpdates]; [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; [self.tableView endUpdates]; } } 

问题是在进行这个调用之后,表格视图会跳回到部分的顶部。 我怎样才能防止这种情况发生,并保持滚动的位置?

啊哈! 我发现了这个问题,并将为将来遇到这个问题的可怜的灵魂回答我自己的问题。

我所有的单元格都有不同的高度,所以我在UITableViewDelegate中使用了新的iOS7方法,认为它可以加快渲染时间(并不是我真的需要它):

 - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath; 

无论如何,实现这个方法的副作用是导致表在调用时跳转到该部分的顶部:

 [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; 

为了解决反弹问题,我只是删除了estimatedHeightForRowAtIndexPath方法的覆盖,现在一切正常。 最后快乐。

你应该能够通过直接更改单元格内容来做你正在做的事情。 例如,如果您使用的是基本UITableViewCell类,并且模型中的数据是您在表视图单元格中显示的NSString ,则可以执行以下操作(更改数据模型之后),而不是调用reloadRowsAtIndexPaths

 UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; UILabel *label = [cell textLabel]; label.text = @"New Value"; 

如果您使用的是UITableViewCell的自定义子类,则除了访问单元格视图之外,其他内容大致相同,都需要通过contentView属性完成。

把单元放在它自己的部分并调用reload部分是可能的:

 [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationFade]; 

这似乎解决了这个问题的一部分。 不是最干净的方式,但它可能会为你工作。

在我的类似的情况下,我不得不调整方法的实施

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { ... } 

我的身高正在被重置。 所以,而不是重新设置每个单元格的高度,我只更新reloadRowsAtIndexPaths调用受影响的单元格。