Search code examples
iosswiftuitableviewreloaddata

Why reload data causes crash when scrollToRow is called after it?


Reloading data causes crash when scrollToRow is called after it. I have to write this code in DispatchQueue.main.async but, why?
Why should I say to switch to the main queue when I have been in the main queue?

self.tableView.reloadData()
print(Thread.current).  // It is main
self.tableView.scrollToRow(at: indexPathToScroll, at: .top, animated: false)
print(Thread.current).  // It is main

The error is:

_contentOffsetForScrollingToRowAtIndexPath:atScrollPosition:usingPresentationValues:]: row (20) beyond bounds (20) for section (0).

The problem was solved in this way:

DispatchQueue.main.async(execute: {
self.tableView.reloadData()
    print(Thread.current).  // It is main
    self.tableView.scrollToRow(at: indexPathToScroll, at: .top, animated: false)
    print(Thread.current).  // It is main
})

As I printed in the first code it was run in the main thread. Why DispatchQueue.main.async made difference?


Solution

  • Simplest answer I found is from GCD Main queue vs Main thread

    While every app will ever only have one main thread, it is possible for many different queues to execute on this one main thread.

    Certain APIs rely not only on running on the main thread, but also on the main queue, it is safer to check for the current queue instead of checking for the current thread.