Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS: How to know reloadData() was completed its task?

I want to scroll to a given index (self.boldRowPath), but when I debug scrollToRow is performed before reloadData().

How to know reloadData has finished ?

func getAllTimeEvent()  {
    self.arrAllTimeEvent = ModelManager.getInstance().getAllTimeEvent(from: self.apportmentDateFrom, to: self.apportmentDateTo)
    self.tblTimeEvent.reloadData()
    self.tblTimeEvent.scrollToRow(at: self.boldRowPath ?? [0,0], at: .top, animated: true)
 }

Any help will be much appreciated.

like image 885
Harshil Kotecha Avatar asked Apr 26 '17 12:04

Harshil Kotecha


3 Answers

Try doing this, it should work:

self.tblTimeEvent.reloadData()
DispatchQueue.main.async(execute: {
    self.tblTimeEvent.scrollToRow(at: self.boldRowPath ?? [0,0], at: .top, animated: true)
})

This will execute the scrollToRow on the main thread, that means after the reloadData is done (because it is on the main thread)

like image 146
Farid Al Haddad Avatar answered Oct 24 '22 06:10

Farid Al Haddad


As explained in this answer, the reload of the UITableView happens on the next layout run (usually, when you return control to the run loop).

So, you can schedule your code after the next layout by using the main dispatch queue. In your case:

    func getAllTimeEvent()  {
        self.arrAllTimeEvent = ModelManager.getInstance().getAllTimeEvent(from: self.apportmentDateFrom, to: self.apportmentDateTo)
        self.tblTimeEvent.reloadData()
        DispatchQueue.main.async {
            self.tblTimeEvent.scrollToRow(at: self.boldRowPath ?? [0,0], at: .top, animated: true)
        }
    }

You can also force the layout by manually calling layoutIfNeeded. But this is generally not a good idea (the previous option is the best):

    func getAllTimeEvent()  {
        self.arrAllTimeEvent = ModelManager.getInstance().getAllTimeEvent(from: self.apportmentDateFrom, to: self.apportmentDateTo)
        self.tblTimeEvent.reloadData()
        self.tblTimeEvent.layoutIfNeeded()
        self.tblTimeEvent.scrollToRow(at: self.boldRowPath ?? [0,0], at: .top, animated: true)
    }
like image 43
Julien Quere Avatar answered Oct 24 '22 06:10

Julien Quere


you can make sure reload is done using...

In Swift 3.0 + we can create a an extension for UITableView with a escaped Closure like below :

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

And Use it like Below where ever you want :

Your_Table_View.reloadData {
   print("reload done")
 }

hope this will help to someone. cheers!

like image 2
Chanaka Anuradh Caldera Avatar answered Oct 24 '22 08:10

Chanaka Anuradh Caldera