scrollToRowAtIndexPath with UITableView does not w

2019-01-21 11:16发布

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.

13条回答
劳资没心,怎么记你
2楼-- · 2019-01-21 12:06

Call scrollToLastPosition() method after loading the tableview like call from viewWillAppear( ) or after table view reload when some thing changed into tableview

func scrollToLastPosition() {
 if !message.isEmpty {
    let indexpath = NSIndexPath(forRow: message.count - 1 , inSection:     0)
    self.tableView.scrollToRowAtIndexPath(indexpath, atScrollPosition: .Bottom, animated: true)
}
}
查看更多
Lonely孤独者°
3楼-- · 2019-01-21 12:09

The better solution is to flip upside down the tableView so you can show new message just by -insertRowsAtIndexPaths:withRowAnimation:

to do it you need first to flip your table by:

_tableView.transform = CGAffineTransformMakeScale (1,-1);

then don't forget to flip back your cells, best place to do it in -awakeFromNib by subclassing:

- (void)awakeFromNib {
    [super awakeFromNib];
    self.contentView.transform = CGAffineTransformMakeScale (1,-1);

//if you have accessoryView
    self.accessoryView.transform = CGAffineTransformMakeScale (1,-1);
}
查看更多
我想做一个坏孩纸
4楼-- · 2019-01-21 12:10

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)
}
查看更多
smile是对你的礼貌
5楼-- · 2019-01-21 12:12

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)
查看更多
叛逆
6楼-- · 2019-01-21 12:13

Heres Swift 3 version

let numberOfSections = self.tableView.numberOfSections
let numberOfRows = self.tableView.numberOfRows(inSection: numberOfSections-1)

if numberOfRows > 0 {
    let indexPath = NSIndexPath.init(row: numberOfRows-1, section: numberOfSections-1)
    self.tableView.scrollToRow(at: indexPath as IndexPath, at: UITableViewScrollPosition.bottom, animated: animated)
}
查看更多
smile是对你的礼貌
7楼-- · 2019-01-21 12:14

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)
        }
    }
}
查看更多
登录 后发表回答