wake-up-neo.com

scrollToRowAtIndexPath mit UITableView funktioniert nicht

Ich habe in iOS8 eine Tabellenansicht wie folgt:

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

Wenn der Benutzer Text über die Tastatur eingibt und sendet, gibt die Anwendung die folgende Methode aus, um die tableView zu scrollen. Ziel ist es, den neuen Text auf dem Bildschirm anzuzeigen (wie ein 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)
        }

Die Tabellenansicht blättert jedoch nicht zum bootom.

Jemand hat eine Lösung?

Vielen Dank.

Erläuterung:

Definition der Klasse: 

class ChatViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextViewDelegate 

dann habe ich die definition der tabellenansicht: 

var tableView: UITableView! 

in viewDidLoad: 

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

dann habe ich den aufruf zum code, der die scroll machen soll (zweiter codeblock auf meiner antwort). Wenn ich die Anwendung starte, erwarte ich, dass die Tabellenansicht nach unten rollen, aber es funktioniert nicht.

20
Kobazzo

Die Lösung unten hat für mich funktioniert. Es ist eine Kombination von Lösungen, die in StackOverflow zu finden sind. Ich rief nach kurzer Verzögerung "scrollToRowAtIndexPath" an.

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

    })
}

angerufen von :

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

Die Lösung bei meinem Problem ist:

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

Laden Sie erst nach, bevor Sie scroll aufrufen. Sehr seltsam, funktioniert aber für iOS 8. 

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

Swift 3 VERSION von @ Fox5150 mit einer Erweiterung:

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

VERWENDUNGSZWECK:

self.tableView.tableViewScrollToBottom(animated: true)
6
Phil

Ich habe das Problem mit einem größeren Index, sagen wir sogar 15. Nur Indizes bis 5-6 können verwendet werden. Durch das Erstellen von "animated: false" hat scrollToRowAtIndexPath () perfekt funktioniert.

2
Imran

Die bessere Lösung ist, die tableView auf den Kopf zu stellen, damit Sie eine neue Nachricht nur mit .__ anzeigen können. -insertRowsAtIndexPaths:withRowAnimation:

um dies zu tun, müssen Sie zuerst Ihren Tisch umdrehen:

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

dann vergessen Sie nicht, Ihre Zellen zurückzudrehen. Am besten können Sie dies in -awakeFromNib durch Unterklassen tun:

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

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

Ich habe das Problem durch Aufrufen von scrollToRow() in der `viewWillLayoutSubviews () gelöst

0
Murat Yasar

Es ist einfach. Führen Sie einfach den Bildlauf in viewDidLayoutSubViews () aus. 

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

Es scheint, als könnte tableview nach Layout-Subviews die richtige Position einnehmen.

0
Lucas Lin

Wenn die Tastatur noch sichtbar ist, müssen Sie die UITableView-Eigenschaft von contentInset einstellen, um die Höhe der Tastatur am unteren Rand des Bildschirms auszugleichen. Andernfalls ist Ihre Zelle möglicherweise hinter der Tastatur verborgen, da UITableView nicht weiß, dass die Hälfte des Inhalts von ihr verborgen ist.

Oder verwenden Sie eine UITableViewController, die das automatisch erledigt.

0
fluidsonic

Ich weiß, dass dies ein älterer Thread ist, aber es ist immer noch relevant. Anstatt sich mit Timeouts zu beschäftigen, die manchmal nicht optimal aufeinander abgestimmt sind, verwenden Sie synchrone Blöcke im Haupt-Thread (normalerweise nichts, was ich tun würde, aber wir sprechen hier von Millisekunden):

DispatchQueue.main.sync {
  // Reload code goes here...
  tableView.reloadData()
}

DispatchQueue.main.sync {
  // Row, section and other checks / initialization go here...
  tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}

Das funktioniert immer bei mir.

0
Aaron

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)
}
0
Pankaj Gaikar

Rufen Sie die scrollToLastPosition () -Methode auf, nachdem Sie die tableview wie den Aufruf von viewWillAppear () aufgerufen haben, oder nach dem erneuten Laden der Tabellensicht, wenn etwas in tableview geändert wird

func scrollToLastPosition() {
 if !message.isEmpty {
    let indexpath = NSIndexPath(forRow: message.count - 1 , inSection:     0)
    self.tableView.scrollToRowAtIndexPath(indexpath, atScrollPosition: .Bottom, animated: true)
}
}
0
bikram sapkota
// 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)
0