wake-up-neo.com

swift ios fügt uitableview eine unendliche Scroll-Paginierung hinzu

Ich frage mich, ob Tableview über eine integrierte Funktion zum Hinzufügen von unendlichen Blättern/Seitenumbrüchen verfügt.

Im Moment sieht mein VC so aus:

var data: JSON! = []

override func viewDidLoad() {
    super.viewDidLoad()

    //Init start height of cell
    self.tableView.estimatedRowHeight = 122
    self.tableView.rowHeight = UITableViewAutomaticDimension

    self.tableView.delegate = self
    self.tableView.dataSource = self

    savedLoader.startAnimation()
    //Load first page
    loadSaved(1)

}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return data.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("aCell") as! SavedTableViewCell

    let info = data[indexPath.row]
    cell.configureWithData(info)

    return cell
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    performSegueWithIdentifier("WebSegue", sender: indexPath)

    tableView.deselectRowAtIndexPath(indexPath, animated: false)
}

Ich hole meine Daten mit loadSaved (1) ab, indem ich der Funktion die aktuelle Seite gebe, die ich laden möchte. Die Funktion fordert eine API-Anforderung mit alomofire an und füllt dann var data: JSON! = [] Mit den Daten, die angezeigt werden sollen

Was ich also tun möchte, ist, wenn ich nach unten in der Tabellenansicht scrolle. LoadSaved (2) sollte aufgerufen werden, um mehr Daten in die Tabellenansicht zu laden

11
user2636197

Das UITableViewDelegate verfügt über eine table-Ansicht (_: will Display: for Row At:) - Instanzmethode , die "dem Delegaten mitteilt, dass die Tabellensicht gerade eine Zelle für eine bestimmte Zeile zeichnet."

In deinem Fall würde ich es so verwenden:

override open func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if indexPath.row == data.count-1 { //you might decide to load sooner than -1 I guess...
      //load more into data here
    }
}

Abhängig von Ihrem Code müssen Sie einige Überprüfungen durchführen, um sicherzustellen, dass Sie nicht in einer Endlosschleife landen, wenn Sie alle Ihre Daten geladen haben.

21
lukkea

Nein, die UITableView hat keine eingebaute Funktion, um die unendlichen Bildlauf- oder Ladefelder on-demand -Zellen wie gewünscht auszuführen. Was Sie verwenden können, ist die Funktion scrollViewDidScroll(_:) im UIScrollViewDelegate, die standardmäßig in UITableView implementiert ist, und auf diese Weise wissen, wann der Benutzer mehr als die in UITableView definierte ursprüngliche Höhe blättert.

Zum Beispiel wie in diesem Code:

var indexOfPageToRequest = 1

override func scrollViewDidScroll(scrollView: UIScrollView) {

    // calculates where the user is in the y-axis
    let offsetY = scrollView.contentOffset.y
    let contentHeight = scrollView.contentSize.height

    if offsetY > contentHeight - scrollView.frame.size.height {

        // increments the number of the page to request
        indexOfPageToRequest += 1

        // call your API for more data
        loadSaved(indexOfPageToRequest)

        // tell the table view to reload with the new data
        self.tableView.reloadData()
    }
}

Um das Ergebnis der Addition der restlichen Elemente am Ende von UITableView zu erhalten, sollten Sie die neuen Elemente zur Datenquelle hinzufügen, in Ihrem Fall data in Ihrer Funktion loadSaved(numberOfPage).

Ich hoffe das hilft dir. 

4
Victor Sigler

Ich habe Victor's Antwort modifiziert und als

var indexOfPageRequest = 1
var loadingStatus = false

func loadData(){
    if !loadingStatus{
        loadingStatus = true
        viewModel.getData(pageIndex: indexOfPageRequest)
    }
}

override func scrollViewDidScroll(_ scrollView: UIScrollView) {

    // calculates where the user is in the y-axis
    let offsetY = scrollView.contentOffset.y
    let contentHeight = scrollView.contentSize.height

    if offsetY > contentHeight - scrollView.frame.size.height {

        // increments the number of the page to request
        indexOfPageRequest += 1

        // call your API for more data
        loadData()

        // tell the table view to reload with the new data
        self.tableView.reloadData()
    }
}

Setzen Sie loadStatus auf true zurück, wenn Sie Daten empfangen. Ohne zu prüfen, ob in der Ansicht bereits mehr Daten geladen wurden, flackerte die Tabellenansicht.

2
Ravi_sankar

Alle obigen Antworten sind korrekt, aber ab iOS 10 haben wir ein sehr schönes Ergebnis

func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath])

Dies ist ein Prefetch-Delegat, der gesetzt werden muss 

tableView.prefetchDataSource = self

RayWeinderlich hat ein Nizza Tutorial zum Thema. Da Rays eine verlässliche Seite ist, gebe ich hier keine Codes ein

0
amar

Oben und sind auch richtig, aber vielleicht hilft jemand aus diesem Code auch.

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath){
    if(indexPath.row == self.arryOfData.count-1){
        if(self.pageNumber <= self.resPgNumber){
            if(remaining != 0){
                let spinner = UIActivityIndicatorView(activityIndicatorStyle: .gray)
                spinner.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: tableView.bounds.width, height: CGFloat(44))
                spinner.startAnimating()
                tableView.tableFooterView = spinner
                tableView.tableFooterView?.isHidden = false

                DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                    self.flgActivity = false
                    self.getActiveOrdersList()
                }
            }
            else{
                tableView.tableFooterView?.removeFromSuperview()
                let view = UIView()
                view.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: tableView.bounds.width, height: CGFloat(5))
                tableView.tableFooterView = view
                tableView.tableFooterView?.isHidden = true
            }
        }
        else{
            tableView.tableFooterView?.removeFromSuperview()
            let view = UIView()
            view.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: tableView.bounds.width, height: CGFloat(5))
            tableView.tableFooterView = view
            tableView.tableFooterView?.isHidden = true
        }
    }
    else{
        tableView.tableFooterView?.removeFromSuperview()
        let view = UIView()
        view.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: tableView.bounds.width, height: CGFloat(5))
        tableView.tableFooterView = view
        tableView.tableFooterView?.isHidden = true
    }
}
0
Vishal Wagh

Ravis Antwort sieht gut aus. Aber wie er am Ende hervorhob, flackert das tableView flackert viel, wenn Sie scrollViewDidScroll(_ scrollView: UIScrollView) verwenden.

Dies liegt daran, dass Sie versuchen, tableView jedes Mal neu zu laden, wenn Sie die tableView durchlaufen. 

Stattdessen können Sie die Delegatenmethode scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) verwenden, um festzustellen, ob Sie ausreichend gescrollt haben und fast das Ende der tableView erreicht haben.

override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {

    let offsetY = scrollView.contentOffset.y
        let contentHeight = scrollView.contentSize.height

        if offsetY > contentHeight - scrollView.frame.size.height {
               indexOfPageRequest += 1
               loadData()
               self.tableView.reloadData()
        }

    }
0
iPhoneDeveloper