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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了调用reloadRowsAtIndexPaths时,UITableView弹回一个部分的顶部相关的知识,希望对你有一定的参考价值。

当用户点击我的一行中的按钮时,我正在更新该行的基础模型,然后为给定的行调用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属性来完成。

另一答案

Swift 4.2

这可以在任何想要删除动画的地方使用。在重新加载表,表部分或任何行期间

 UIView.performWithoutAnimation({
                cell.configureSelection(isSelected: true)
                tableView.reloadSections([1], with: .none)
                tableView.allowsSelection =  false

            })
另一答案

可以将单元格放在它自己的部分并调用重载部分:

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

这似乎部分地解决了这个问题。不是最干净的方式,但它可能对你有用。

另一答案

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

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

我的高度被重置的地方。因此,我没有为每个单元格重置高度,而是仅更新了受影响的单元格以进行reloadRowsAtIndexPaths调用。

另一答案

这对我有用。

UIView.setAnimationsEnabled(false)
tableView.reloadRows(at: [...], with: .none)
UIView.setAnimationsEnabled(true)
另一答案

如果您知道单元格的最小高度,则必须在设置estimatedRowHeight时指定。我把它设置为1,因为我在某处读过任何超过0的值就足以达到目的,但这是罪魁祸首。

当我将它设置为44,这是我的细胞所能达到的最小高度时,一切都很顺利。

动态高度也很好,这个修复没有问题。

另一答案

为了建立xsee的答案 - 我已经将界面构建器中的Estimate设置为“自动”。我将其更改为另一个号码,它开始工作。我保持Row Height自动。

另一答案

我遇到过同样的问题。我最后只是在更新我的数据/单元后调用tableView.reloadData()并且它没有弹回到顶部/数据已更新到位 - 仅供参考

以上是关于调用reloadRowsAtIndexPaths时,UITableView弹回一个部分的顶部的主要内容,如果未能解决你的问题,请参考以下文章

iOS调用reloadRowsAtIndexPaths Crash报异常NSInternalInconsistencyException

UITableView 的 reloadRowsAtIndexPaths: (NSArray *) indexPaths 无法导致重新加载,除非你调用它两次?

UITableView reloadRowsAtIndexPaths 图形故障

reloadRowsAtIndexPaths 时保持偏移

如何覆盖 reloadRowsAtIndexPath?

iOS Swift 和 reloadRowsAtIndexPaths 编译错误