scrollToRowAtIndexPath with UITableView does not work
Solution 1
The solution below worked for me. It's a combination of solutions found on StackOverflow. I called "scrollToRowAtIndexPath
" after a very short delay.
func tableViewScrollToBottom(animated: Bool) {
let delay = 0.1 * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue(), {
let numberOfSections = self.tableView.numberOfSections()
let numberOfRows = self.tableView.numberOfRowsInSection(numberOfSections-1)
if numberOfRows > 0 {
let indexPath = NSIndexPath(forRow: numberOfRows-1, inSection: (numberOfSections-1))
self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: animated)
}
})
}
called by :
tableViewScrollToBottom(true)
Swift 3
func tableViewScrollToBottom(animated: Bool) {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {
let numberOfSections = self.tableView.numberOfSections
let numberOfRows = self.tableView.numberOfRows(inSection: numberOfSections-1)
if numberOfRows > 0 {
let indexPath = IndexPath(row: numberOfRows-1, section: (numberOfSections-1))
self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: animated)
}
}
}
Solution 2
The solution at my problem is:
let numberOfSections = tableView.numberOfSections()
let numberOfRows = tableView.numberOfRowsInSection(numberOfSections-1)
if numberOfRows > 0 {
println(numberOfSections)
let indexPath = NSIndexPath(forRow: numberOfRows-1, inSection: (numberOfSections-1))
tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: animated)
}
Solution 3
SWIFT 3 VERSION of @Fox5150 answer, with an extension :
extension UITableView {
func tableViewScrollToBottom(animated: Bool) {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
let numberOfSections = self.numberOfSections
let numberOfRows = self.numberOfRows(inSection: numberOfSections-1)
if numberOfRows > 0 {
let indexPath = IndexPath(row: numberOfRows-1, section: (numberOfSections-1))
self.scrollToRow(at: indexPath, at: UITableViewScrollPosition.bottom, animated: animated)
}
}
}
}
USAGE:
self.tableView.tableViewScrollToBottom(animated: true)
Solution 4
Try reloading first before calling scroll. Very weired but works for iOS8.
tableView.reloadData()
tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: animated)
Solution 5
I have the problem with a bigger index say even 15. Only indexes till 5-6 use to work. By making "animated: false" scrollToRowAtIndexPath() worked perfectly.
Related videos on Youtube
Kobazzo
Updated on April 01, 2022Comments
-
Kobazzo about 2 years
I have in iOS8 a table view like this:
tableView = UITableView(frame: view.bounds, style: .Plain) view.addSubview(tableView)
When the user types and sends some text in the keyboard, the application ivoke the following method to scroll the tableView. The goal is to view the new text in the screen (like a chat)
let numberOfRows = tableView.numberOfRowsInSection(0) if numberOfRows > 0 { let indexPath = NSIndexPath(forRow: numberOfRows-1, inSection: 0) tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: animated) }
But the table view does not scroll to the bootom.
Someone has a solution?
Thank you.
Explanation:
Definition of the class:
class ChatViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextViewDelegate
then I have the definition of the table view:
var tableView: UITableView!
in viewDidLoad:
tableView = UITableView(frame: view.bounds, style: .Plain) tableView.dataSource = self tableView.delegate = self view.addSubview(tableView)
then I have the call to the code that should make the scroll (second block of code on my answer). When I launch the application I expect the tableview to scroll down, but it does not work.
-
Kobazzo over 9 yearsThank you, later i'll try this solution.
-
fluidsonic over 9 yearsA little more context is necessary then. Can you share more code please?
-
Kobazzo over 9 yearsDefinition of the class: class ChatViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextViewDelegate the definition of the table view: var tableView: UITableView! in viewDidLoad: tableView = UITableView(frame: view.bounds, style: .Plain) tableView.dataSource = self tableView.delegate = self view.addSubview(tableView) ... cal to the code that sould make the scroll (second block of code on my answer). When I launch the application I expect the tableview scrolls down, but does not work
-
fluidsonic over 9 yearsPlease edit your original question to add new code. This is barely readable.
-
fluidsonic over 9 yearsThis is still not enough code to understand how and when you scroll to the last cell. Can you show the whole process from the point where the message is added until the scroll happens (which you already posted)? -- You should also check out SlackTextViewController - maybe you find it helpful as it seems to do what you're looking for.
-
Manuel over 8 yearsThis is the best solution I found so far. I had to increase the delay to 0.5 though otherwise it would sometimes be called before tableView.reloadData has finished. I tried about every solution on SO (subclass
TableViewDelegate
and overridereloadData
; execute on main thread withdispatch_asynch
, etc.) to scroll to bottom, none of them seem to work anymore for iOS 9. -
jcady over 8 yearsiOS 9 broke other methods for scrolling to the bottom of a table. But this one works.
-
nmdias about 8 yearsI needed to update a table view's scroll position that isn't visible when the scroll is taking place and this worked for me. Tested on iOS9. Also, It's not that it didn't scroll, but it didn't scroll completely in all instances. Now it does.
-
jose920405 about 8 yearscause crash in
let numberOfRows = tableView.numberOfRowsInSection(numberOfSections-1)
ifnumberOfSections
is 0 -
iOS_Developer about 7 yearsThis didn't help me ....I have to scroll manually to see the contents for last row. there is nothing wrong with table view and its content size because manual scroll shows the contents properly.
-
MEnnabah almost 7 yearsThis is not scrolling at all. And please, check the code as you're not using the arguments parentheses in your func
-
Evgeniy Kleban over 6 yearsIt works but i wonder if there is any way to do this without dispatch after?
-
Antoine Rucquoy over 5 yearsWHAT IS THIS SORCERY
-
Luke almost 5 yearsUsing "DispatchQueue" worked for me too in 2019, with Swift 5. scrollToRow was not working without delaying it by using "DispatchQueue". Can someone please explain its reason? Why a delay is necessary?
-
SleepNot about 4 yearsscrollToRow is one of the most frustrating things to use in iOS. I am already adding a delay but sometimes it doesn't scroll all the way through the bottom.
-
Ankush Bhatia about 4 yearsI will never support this solution as blocking main thread simply does not mean that we are just blocking UI, we might be blocking something else running on that queue.
-
Dave Y almost 4 yearsWorks in 2020 for my related issue - thanks for the idea! For info I had some bad behaviour when scrolling to a position during a scrollView bounce. i.e. if the scrollView is still offset from a scroll bounce, jumping to a certain scroll position can misbehave. Delaying the scrollToRow by 100ms cleaned this up. Perfecto.