关于swift:UITableview在重新加载时滚动到顶部

UITableview Scrolls to Top on Reload

我的应用程序遇到问题-您可以发布和编辑自己喜欢的地方。发布帖子或编辑特定帖子(UITableViewCell)后,重新加载UITableview

我的问题是:UITableview重新加载后滚动到顶部。但这不是我想要的。我希望我的视图停留在原来的单元格/视图上。但是我不知道该如何处理。

你能帮我吗?


如果您使用的是可动态调整大小的单元格(UITableViewAutomaticDimension),则Igor的答案是正确的

这里很快3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    private var cellHeights: [IndexPath: CGFloat?] = [:]
    var expandedIndexPaths: [IndexPath] = []

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        cellHeights[indexPath] = cell.frame.height
    }

    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        if let height = cellHeights[indexPath] {
            return height ?? UITableViewAutomaticDimension
        }
        return UITableViewAutomaticDimension
    }


    func expandCell(cell: UITableViewCell) {
      if let indexPath = tableView.indexPath(for: cell) {
        if !expandedIndexPaths.contains(indexPath) {
            expandedIndexPaths.append(indexPath)
            cellHeights[indexPath] = nil
            tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
            //tableView.scrollToRow(at: indexPath, at: .top, animated: true)
        }
      }
    }


为防止滚动到顶部,应在加载单元格时保存它们的高度,并在tableView:estimatedHeightForRowAtIndexPath

中提供确切的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// declare cellHeightsDictionary
NSMutableDictionary *cellHeightsDictionary;

// initialize it in ViewDidLoad or other place
cellHeightsDictionary = @{}.mutableCopy;

// save height
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    [cellHeightsDictionary setObject:@(cell.frame.size.height) forKey:indexPath];
}

// give exact height value
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSNumber *height = [cellHeightsDictionary objectForKey:indexPath];
    if (height) return height.doubleValue;
    return UITableViewAutomaticDimension;
}


UITableViewreloadData()方法显式是强制重新加载整个tableView。它运作良好,但如果要使用用户当前正在查看的表视图来进行操作,通常会感到不舒服,并且会给用户带来不良的体验。

相反,请查看文档中的reloadRowsAtIndexPaths(_:withRowAnimation:)
reloadSections(_:withRowAnimation:)


如果您想要一个简单的解决方案,只需走这些行

1
2
3
let contentOffset = tableView.contentOffset
tableView.reloadData()
tableView.setContentOffset(contentOffset, animated: false)

快速3.1

1
2
3
4
5
6
DispatchQueue.main.async(execute: {

    self.TableView.reloadData()
    self.TableView.contentOffset = .zero

})