2015-11-14 10 views
13

Ich habe eine UITableView, die mit Zellen mit dynamischer Höhe gefüllt ist. Ich möchte, dass die Tabelle nach unten scrollt, wenn der View-Controller vom View-Controller gedrückt wird.Wie scrollt man zum genauen Ende des UITableView?

Ich habe versucht mit contentOffset und tableView scrollToRowAtIndexPath aber immer noch bekomme ich nicht die perfekte Lösung für genau ich will.

Kann mir bitte jemand helfen, dieses Problem zu beheben?

Hier ist mein Code zu blättern:

let indexPath = NSIndexPath(forRow: commentArray.count-1, inSection: 0) 
tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: true) 
+1

Wann rufen Sie diese Zeile an. Das ist von höchster Wichtigkeit. Sie möchten dies nicht aufrufen, bevor die Tabellenansicht ausgefüllt wurde. –

+0

Ya ich rief diese Zeile nach der Tabellenansicht reloaded – Padmaja

+0

Das ist nicht genug. Sie sehen, 'reloadData' scheint zwar synchron zu sein, verhält sich aber asynchron. Sie müssen also entweder Ihren Code in einen 'dispatchAsync'-Block im Hauptthread einschließen oder einen anderen Weg finden, dies zu tun. Ich habe viele Male mit diesem Problem konfrontiert. Das Scrollen zu einem bestimmten Indexpfad ist fast immer sinnlos. Sie sollten die Methode 'setContentOffset' verwenden. –

Antwort

5

Wenn Sie die Viewcontroller mit dem Tableview schieben sollten Sie scrollTo die angegebene indexPath nur nach dem Tableview Nachladen beendet ist.

yourTableview.reloadData() 
dispatch_async(dispatch_get_main_queue(), {() -> Void in 
    let indexPath = NSIndexPath(forRow: commentArray.count-1, inSection: 0) 
    tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: true) 

}) 

Der Grund für das Verfahren in der dispatch_async setzen ist, wenn Sie reload die nächste Zeile sofort ausgeführt wird erhalten ausführen und dann wird in Haupt-Thread passiert erneut zu laden. Um zu wissen, wann die Tabellenansicht beendet ist (nachdem der cellforrowindex beendet ist), verwenden wir GCD hier. Grundsätzlich gibt es keinen Delegaten in der Tabellenansicht, der anzeigt, dass die Tabellenansicht neu geladen wurde.

+0

Vielen Dank für die Lösung.Wenn ich diesen Code anwenden funktioniert besser als zuvor, aber immer noch das Problem exits.Its nicht Scrollen bis zur letzten Zeile. – Padmaja

+0

Was passiert eigentlich, wenn Sie diesen Code eingeben? – iPrabu

+0

Wenn die Tabellenansicht zuletzt ausgefüllt ist, bleiben 5 bis 6 Zellen übrig. – Padmaja

27

Für Swift 3,0

Schreiben Sie eine Funktion:

func scrollToBottom(){ 
    DispatchQueue.main.async { 
     let indexPath = IndexPath(row: self.dataArray.count-1, section: 0) 
     self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: true) 
    } 
} 

und es nennen, nachdem Sie die Tableview Daten nachladen

tableView.reloadData() 
scrollToBottom() 
+5

Unsicher: '' 'Diese Anwendung ändert die Auto-Layout-Engine von einem Hintergrund-Thread, nachdem auf die Engine vom Haupt-Thread zugegriffen wurde. Dies kann zu Motorschäden und seltsamen Abstürzen führen. '' ' – Jeremie

+0

@Jeremie Bitte fügen Sie die UI-Änderungen der Hauptwarteschlange hinzu, um diese Warnung zu vermeiden –

+0

Ich aktualisierte die Antwort, um dieses Update auf dem Hauptthread durchzuführen. –

-1

Das in Swift arbeitet 3,0

let pointsFromTop = CGPoint(x: 0, y: CGFloat.greatestFiniteMagnitude) 
tableView.setContentOffset(pointsFromTop, animated: true) 
+0

Meine Tabellenansicht wurde unbrauchbar gemacht, da keine Daten angezeigt werden und iOS 11, Swift 4, Xcode 9 – ekscrypto

-1

Arbeiten in Swift 3+:

 self.tableView.setContentOffset(CGPoint(x: 0, y: self.tableView.contentSize.height - UIScreen.main.bounds.height), animated: true) 
+0

nicht gescrollt werden kann. Dies hat mehrere Probleme. Zum einen kann die Tabellenansicht nicht den gesamten Bildschirm einnehmen, Sie ignorieren Navigationsleisten, Suchleisten und andere Elemente, die den Anzeigebereich der Tabellenansicht beeinflussen können. Sie ignorieren auch alle Inhaltseinfügungen, die möglicherweise für die Tabelle festgelegt wurden. – ekscrypto

0

Wenn Sie UINavigationBar mit einem gewissen Höhe und UITableView im UIView verwendet versuchen, es UINavigationBar Höhe von UITableView ‚s Rahmenhöhe zu subtrahieren. Ursache Ihr UITableView 's top Punkt gleich mit UINavigationBar' sPunkt, so dass dies Ihre UITableView 's bottom Elemente zu scrollen.

Swift 3

simpleTableView.frame = CGRect.init(x: 0, y: navigationBarHeight, width: Int(view.frame.width), height: Int(view.frame.height)-navigationBarHeight) 
0

[Swift 3, iOS 10]

Ich habe mit Art-of-Hacky endete Lösung, aber es hängt nicht von Reihen indexpaths (was manchmal zu Abstürzen führt), zellen dynamisches höhe oder table reload event, so scheint es ziemlich universell und in der Praxis funktioniert zuverlässiger als andere, die ich gefunden habe.

  • Verwendung KVO Contenttisch

  • Feuer scroll Ereignis innerhalb KVO Beobachter

  • Zeitplan scroll Aufruf unter Verwendung verzögerter Timer zum Erfassen mehrerer
    Beobachter triggert

Die filtern Code in einigen ViewController:

private var scrollTimer: Timer? 
private var ObserveContext: Int = 0 

override func viewWillAppear(_ animated: Bool) { 
    super.viewWillAppear(animated) 
    table.addObserver(self, forKeyPath: "contentSize", options: NSKeyValueObservingOptions.new, context: &ObserveContext) 
} 

override func viewWillDisappear(_ animated: Bool) { 
    super.viewWillDisappear(animated) 
    table.removeObserver(self, forKeyPath: "contentSize") 
} 

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 
    if (context == &ObserveContext) { 
     self.scheduleScrollToBottom() 
    } 
} 

func scheduleScrollToBottom() { 

    if (self.scrollTimer == nil) { 
     self.scrollTimer = Timer(timeInterval: 0.5, repeats: false, block: { [weak self] (timer) in 
      let table = self!.table 

      let bottomOffset = table.contentSize.height - table.bounds.size.height 
      if !table.isDragging && bottomOffset > 0 { 
       let point: CGPoint = CGPoint(x: 0, y: bottomOffset) 
       table.setContentOffset(point, animated: true) 
      } 

      timer.invalidate() 
      self?.scrollTimer = nil 
     }) 
     self.scrollTimer?.fire() 
    } 
} 
Verwandte Themen