iOS TableView reload and scroll top

2019-01-11 21:12发布

问题:

the second day I can not solve the problem with the table.

We have a segmentedControl which, when changed, changes the table. 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.

And it seems like everything is simple: contentOffset = .zero and 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 ()

Maybe I can not understand the obvious things)) Congrats on the upcoming holidays!

回答1:

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.

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
    }
}


回答2:

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)


回答3:

you can use this.

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

you can set animated as your requirement



回答4:

I was getting the following error after trying to scroll to top straight after calling a 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)
    }