调用reloadRowsAtIndexPaths时,UITableView弹回一个部分的顶部

xse*_*see 37 objective-c uitableview ios ios7

当用户点击我的一行中的按钮时,我正在更新该行的基础模型,然后为给定行调用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];
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是在进行此调用后,表视图会弹回到该部分的顶部.如何防止这种情况发生并将滚动位置保持在原位?

xse*_*see 47

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

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

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath;
Run Code Online (Sandbox Code Playgroud)

无论如何,实现这种方法有一个邪恶的副作用,导致表调用时反弹到该部分的顶部:

[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
Run Code Online (Sandbox Code Playgroud)

为了解决反弹问题,我刚刚删除了estimatedHeightForRowAtIndexPath方法的覆盖,现在一切正常.终于快乐了.

  • 我有同样的问题,除了我实际上想要使用estimatedRowHeight.我发现通过将estimatedRowHeight设置为大于单元格实际高度的数字似乎稍微改善了行为(表格视图只滚动了一点). (24认同)
  • 虽然这个问题没有真正的解决方案吗?这似乎是Apple的一个错误? (8认同)
  • 在iOS8中使用UITableViewAutomaticDimension时需要estimatedRowHeight. (3认同)
  • 我在`viewDidLoad`中设置`estimatedRowHeight = tableView.rowHeight`,这似乎有点帮助.我也在使用`UITableViewAutomaticDimension`. (3认同)
  • 你好@xsee,如果我使用的是autoLayout,如果我不使用extimatedRowHeight,那么在添加时会出现问题并且行会缩小 (2认同)
  • 奇怪的问题,正在寻找解决方案.在我的例子中,我使用了自我调整单元格和estimatedRowHeight.我只是将estimatedRowHeight的值更改为大于单元格的高度.现在效果不错. (2认同)

小智 5

这对我有用。

UIView.setAnimationsEnabled(false)
tableView.reloadRows(at: [...], with: .none)
UIView.setAnimationsEnabled(true)
Run Code Online (Sandbox Code Playgroud)