简体   繁体   English

iOS TableView 重新加载并滚动到顶部

[英]iOS TableView reload and scroll top

the second day I can not solve the problem with the table.第二天我无法解决表的问题。

We have a segmentedControl which, when changed, changes the table.我们有一个 segmentedControl,它在更改时会更改表格。 Suppose that there are 3 elements in the segment of the control and, correspondingly, 3 arrays (which is important, they are of different sizes) I need to scroll table up when segmentedControl is changed.假设控件的段中有 3 个元素,相应地有 3 个 arrays(这很重要,它们的大小不同)我需要在更改 segmentedControl 时向上滚动表。

And it seems like everything is simple: contentOffset =.zero and reloadData ()看起来一切都很简单:contentOffset =.zero 和 reloadData ()

But.但。 This does not work, I do not know why the table not scroll up.这不起作用,我不知道为什么表格不向上滚动。

The only thing that worked:唯一有效的是:

UIView.animate (withDuration: 0.1, animations: {
            self.tableView.contentOffset = .zero
        }) {(_) in
            self.tableView.reloadData ()
}

But now there is another problem when the table goes up, a bug may occur, because the segmentedControl has changed, and the data in the other array may not be, we have not yet done reloadData ()但是现在表上去还有一个问题,可能会出现bug,因为segmentedControl变了,而另一个数组里面的数据可能不是,我们还没有做reloadData()

Maybe I can not understand the obvious things)) Congrats on the upcoming holidays!也许我无法理解显而易见的事情))祝贺即将到来的假期!

UItableView method scrollToRow(at:at:animated:) Scrolls through the table view until a row identified by index path is at a particular location on the screen. UItableView方法scrollToRow(at:at:animated:)滚动表格视图,直到由索引路径标识的行位于屏幕上的特定位置。

Use使用

tableView.scroll(to: .top, animated: true)

You can use my extension你可以使用我的扩展

extension UITableView {

    public func reloadData(_ completion: @escaping ()->()) {
        UIView.animate(withDuration: 0, animations: {
            self.reloadData()
        }, completion:{ _ in
            completion()
        })
    }

    func scroll(to: scrollsTo, animated: Bool) {
        DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {
            let numberOfSections = self.numberOfSections
            let numberOfRows = self.numberOfRows(inSection: numberOfSections-1)
            switch to{
            case .top:
                if numberOfRows > 0 {
                     let indexPath = IndexPath(row: 0, section: 0)
                     self.scrollToRow(at: indexPath, at: .top, animated: animated)
                }
                break
            case .bottom:
                if numberOfRows > 0 {
                    let indexPath = IndexPath(row: numberOfRows-1, section: (numberOfSections-1))
                    self.scrollToRow(at: indexPath, at: .bottom, animated: animated)
                }
                break
            }
        }
    }

    enum scrollsTo {
        case top,bottom
    }
}

I was getting the following error after trying to scroll to top straight after calling a reloadData在调用 reloadData 后尝试直接滚动到顶部后,我收到以下错误

[UITableView _contentOffsetForScrollingToRowAtIndexPath:atScrollPosition:]: row (0) beyond bounds (0) for section (0).'

This fixed it for me:这为我修复了它:

    tableView.reloadData()
    if tableView.numberOfRows(inSection: 0) != 0 {
        tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
    }

I found better way to do this.我找到了更好的方法来做到这一点。 It works like a charm.它就像一个魅力。

let topIndex = IndexPath(row: 0, section: 0)
tableView.scrollToRow(at: topIndex, at: .top, animated: true)

Okay.好的。 So people finding issue with scrolling a tableview to the top with所以人们发现将 tableview 滚动到顶部的问题

self.tableView.setContentOffset(.zero, animated: false)

And need to do reload data unnecessarily to fix this !并且需要做不必要的重新加载数据来解决这个问题!

So What is the issue with setContentOffset is kind of bug of iOS ?那么setContentOffset有什么问题是 iOS 的一种错误?
The smallest and simplest answer is NO so what's the issue then ?最小和最简单的答案是否定的那么问题是什么?

The answer is that dynamic row is using UITableView.automaticDimension .答案是动态行正在使用UITableView.automaticDimension Tableview calculates its content offset with row height and with the number or sections and rows you have in your data source. Tableview 使用行高以及数据源中的数量或部分和行来计算其内容偏移量。 So in case of dynamic height is not performing the scrollToTop correctly, it is because it needs to recalculate every row height and content size.所以在动态高度没有正确执行 scrollToTop 的情况下,这是因为它需要重新计算每个行高和内容大小。

So to reduce this bundle from tableview we, can provide an estimated row height like所以为了从 tableview 中减少这个包,我们可以提供一个估计的行高,比如

self.tableView.estimatedRowHeight = 117 // whatever your value 

Hopefully this will help someone :)希望这会帮助某人:)

Perfectly to the top of page on reload, by twice reloading通过两次重新加载,完美地在重新加载时到达页面顶部

No disturbing animation没有令人不安的动画

dataForSource = nil
tableView.reloadData()

DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
    self.dataForSource = realData
    self.tableView.reloadData()
}

you can use this.你可以用这个。

    tableView.setContentOffset(CGPoint.zero, animated: true)

you can set animated as your requirement您可以将动画设置为您的要求

Swift 5.1 *, tried one line code and worked for me: Swift 5.1 *,尝试了一行代码并为我工作:

tableView?.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)

Added this code to my tableview to align the content to start from top.将此代码添加到我的 tableview 以对齐内容以从顶部开始。

Hope will be helping.希望会有所帮助。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM