Подтвердить что ты не робот

ScrollToRowAtIndexPath с UITableView не работает

У меня в iOS8 есть табличный вид:

tableView = UITableView(frame: view.bounds, style: .Plain)
view.addSubview(tableView)

Когда пользователь вводит и отправляет некоторый текст на клавиатуре, приложение выполняет следующий метод для прокрутки таблицыView. Цель состоит в том, чтобы просмотреть новый текст на экране (например, чат).

let numberOfRows = tableView.numberOfRowsInSection(0)
        if numberOfRows > 0 {
            let indexPath = NSIndexPath(forRow: numberOfRows-1, inSection: 0)
            tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: animated)
        }

Но в представлении таблицы нет прокрутки к загрузке.

У кого-то есть решение?

Спасибо.

Пояснение:

Определение класса:

class ChatViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextViewDelegate 

то у меня есть определение вида таблицы:

var tableView: UITableView! 

in viewDidLoad:

tableView = UITableView(frame: view.bounds, style: .Plain) 
tableView.dataSource = self 
tableView.delegate = self 
view.addSubview(tableView) 

то у меня есть вызов кода, который должен сделать прокрутку (второй блок кода в моем ответе). Когда я запускаю приложение, я ожидаю, что tableview будет прокручиваться вниз, но он не работает.

4b9b3361

Ответ 1

Решение ниже работало для меня. Это комбинация решений, найденных в StackOverflow. Я вызвал "scrollToRowAtIndexPath" после очень короткой задержки.

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

    })
}

вызванный:

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

Ответ 2

Решение по моей проблеме:

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

Ответ 3

Попробуйте перезагрузить сначала, прежде чем вызывать прокрутку. Очень хорошо, но работает для iOS8.

   tableView.reloadData()
   tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: animated)

Ответ 4

SWIFT 3 VERSION @Fox5150 ответьте с расширением:

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

ПРИМЕНЕНИЕ:

self.tableView.tableViewScrollToBottom(animated: true)

Ответ 5

Лучшее решение - перевернуть вверх дном tableView, чтобы вы могли показывать новое сообщение только  -insertRowsAtIndexPaths:withRowAnimation:

для этого вам нужно сначала перевернуть таблицу:

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

то не забудьте перевернуть свои ячейки, лучше всего сделать это в -awakeFromNib путем подкласса:

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

//if you have accessoryView
    self.accessoryView.transform = CGAffineTransformMakeScale (1,-1);
}

Ответ 6

Если клавиатура все еще видна, вам необходимо установить свойство UITableView contentInset, чтобы компенсировать высоту клавиатуры в нижней части экрана. В противном случае ваша ячейка может быть скрыта за клавиатурой, потому что UITableView не знает, что ее содержимое скрыто.

Или используйте UITableViewController, который обрабатывает это автоматически.

Ответ 7

У меня проблема с большим индексом, скажем, даже 15. Только для индексов до 5-6 использовать. Сделав "анимированный: false", scrollToRowAtIndexPath() работал отлично.

Ответ 8

Вызвать метод scrollToLastPosition() после загрузки tableview как вызов из viewWillAppear() или после перезагрузки таблицы, когда какая-то вещь изменилась в tableview

func scrollToLastPosition() {
 if !message.isEmpty {
    let indexpath = NSIndexPath(forRow: message.count - 1 , inSection:     0)
    self.tableView.scrollToRowAtIndexPath(indexpath, atScrollPosition: .Bottom, animated: true)
}
}

Ответ 9

Версия Heres Swift 3

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

Ответ 10

// First figure out how many sections there are
 let lastSectionIndex = self.tblTableView!.numberOfSections() - 1

// Then grab the number of rows in the last section

let lastRowIndex = 
self.tblTableView!.numberOfRowsInSection(lastSectionIndex) - 1

// Now just construct the index path

let pathToLastRow = NSIndexPath(forRow: lastRowIndex, inSection: lastSectionIndex)

// Make the last row visible
self.tblTableView?.scrollToRowAtIndexPath(pathToLastRow, atScrollPosition: UITableViewScrollPosition.None, animated: true)

Ответ 11

Это просто. Просто выполните операцию прокрутки в viewDidLayoutSubViews()

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.scrollToBottom(animated: false)
}

fileprivate func scrollToBottom(animated: Bool) {
    if self.items.count > 0 {
        let lastIndex = IndexPath(row: items.count - 1, section: 1)
        self.tableView.scrollToRow(at: lastIndex, at: .bottom, animated: animated)
    }
}

Кажется, что tableview может получить правильный positon после просмотра макета.

Ответ 12

Все вышеприведенные коды являются точными, но в моем случае, когда я хочу загрузить tableView, а также прокрутить вниз до tableView мгновенно, когда контроллер загружает, поскольку для этой ситуации выше методов требуется некоторое время для прокрутки до нижней части tableView. Поэтому я следил за этими кодами.

Заменить tableView reload как

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

Написанный прокрутка до нижнего метода следующим образом:

func tableViewScrollToBottom
{
     if self.tblChat.contentSize.height > self.tblChat.frame.size.height
     {
         let offset:CGPoint = CGPoint(x: 0,y :self.tblChat.contentSize.height-self.tblChat.frame.size.height)
         self.tblChat.setContentOffset(offset, animated: false)
     }
 }

а затем перезагрузите tableView, когда загрузка данных завершается с веб-службы или с любого основного объекта данных:

tblChat.reloadData()
{
     self.tableViewScrollToBottom
}

Теперь он работает плавно, как я хотел.