Georg Weber
Georg Weber

Reputation: 45

How I can add pagination in swift?

I have spend so much time to find a solution with the documentation from Firebase without any success. I using Swift 5.3 and Firestore and have the following code:

func readFlights() {
        Spinner.startAnimating()
         let myquery = db.collection("flight").limit(to: 25).whereField("Userid", isEqualTo: userID).order(by: "DateDB", descending: true)
            .order(by: "Start", descending: true)
         myquery.getDocuments() { (querySnapshot, err) in
            if let err = err {
                print("Error getting documents: \(err)")
            } else {
                for document in querySnapshot!.documents {
                    self.prefixArray.append(document.get("Prefix") as! String)
                    self.dateArray.append(document.get("Date") as! String)
                    self.startArray.append(document.get("Start") as! String)
                    self.stopArray.append(document.get("Stop") as! String)
                    self.landingArray.append(document.get("Landing") as! String)
                    self.takeOffArray.append(document.get("Takeoff") as! String)
                    self.flightTimeArray.append(document.get("FlightTime") as! String)
                    self.engineTimeArray.append(document.get("EngineTime") as! String)
                    self.idArray.append(document.get("id") as! String)
                    self.destinationArray.append(document.get("Destination") as! String)
                    self.originArray.append(document.get("Origin") as! String)
                    self.informationArray.append(document.get("Addinfo") as! String)
                    self.rulesArray.append(document.get("VFRIFR") as! Int)
                    self.pilotCopilotArray.append(document.get("PilotoCopiloto") as! Int)
                    self.engineArray.append(document.get("MnteMlte") as! Int)
                    self.dayNightArray.append(document.get("DayNight") as! Int)
                }
                DispatchQueue.main.async{
                self.tabelView.reloadData()
                self.Spinner.stopAnimating()
                }
            }
        }

working fine but I need to include in this code pagination. That means when I received the first 25 records from Firestore and I slip down in the list with my finger so I want after the latest record he load 25 records more and show them.

I would appreciate your help. Thank you

Upvotes: 0

Views: 186

Answers (3)

slushy
slushy

Reputation: 12385

First, create a document cursor that is an instance property of the view/view controller:

var cursor: DocumentSnapshot?
let pageSize = 25 // for convenience

Second, apply the page size to the query:

let myquery = db.collection("flight").limit(to: pageSize).whereField("Userid", isEqualTo: userID).order(by: "DateDB", descending: true).order(by: "Start", descending: true)

Third, whenever you receive a snapshot from Firestore, update the cursor at some point in the return (ideally, after you've unwrapped the snapshot and before you've parsed the documents):

func getData() {
    myquery.getDocuments(completion: { (snapshot, error) in
        ...
        if snapshot.count < pageSize {
            /* this return had less than 25 documents, therefore
               there are no more possible documents to fetch and
               thus there is no cursor */
            self.cursor = nil
        } else {
            /* this return had at least 25 documents, therefore
               there may be more documents to fetch which makes
               the last document in this snapshot the cursor */
            self.cursor = snapshot.documents.last
        }
        ...
    })
}

Finally, whenever the user scrolls to the bottom, fetch another page using the cursor:

func continueData() {
    guard let cursor = cursor else {
        return // no cursor, exit
    }
    myquery.start(afterDocument: cursor).getDocuments(completion: { (snapshot, error) in
        ...
        // always update the cursor whenever Firestore returns
        if snapshot.count < self.pageSize {
            self.cursor = nil
        } else {
            self.cursor = snapshot.documents.last
        }
        ...
    })
}

For a fluid user experience, you will need to greatly refine this code, but this is the foundation from which you can paginate Firestore. You can also paginate in Firestore using a document offset (instead of a document cursor) but this is to be avoided (refer to documentation for the reasons).

Upvotes: 1

Farrukh Makhmudov
Farrukh Makhmudov

Reputation: 472

By using UITableViewDelegate, u can call the function. Each time when you scroll to the bottom, it will check the max of your limit and if the condition is true, then fetch data again.

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    let lastItem = self.array.count - 1
    if indexPath.row == lastItem {
        if limit < max_limit {
            limit += 25
           //Get data from Server
           readFlights(limit:Int)
        }
    }
}

The max_limit means the total amount of limits, usually, it returned by server in meta

Upvotes: 0

Maxim Zakopaylov
Maxim Zakopaylov

Reputation: 556

You can use awesome solution from: https://github.com/pronebird/UIScrollView-InfiniteScroll

For your example:

tableView.addInfiniteScroll { (tableView) -> Void in
    readFlights("offset if need")
    tableView.finishInfiniteScroll()
}

Upvotes: 0

Related Questions