[SOLVED] Swift Firebase get batches of documents in order

Issue

For context, I have a bunch of documents that hold fields similar to a social media post. (photo url link, like count, date uploaded, person who uploaded it, etc.) And I am showing this data in a gallery (lazyvgrid). I do not want to get all of the documents at once so when the user scrolls down the gallery I am getting 20 documents at a time based on how far the user scrolls down the gallery view. I am sorting my get request with:

self.eventsDataCollection.document(currentEventID).collection("eventMedias").order(by: "savesCount", descending: true).limit(to: 20).getDocuments

I have no problem getting the first 20 using this code. How can I get the next 20 and the 20 after that, and so on?

Solution

I ended up referencing Dharmaraj’s link in his comment.

@Published var isFetchingMoreDocs: Bool = false
private var lastDocQuery: DocumentSnapshot!
    public func getUpdatedEventMedias(currentEventID: String, eventMedias: [EventMedia], completion: @escaping (_ eventMedias: [EventMedia]) -> Void) {
        self.isFetchingMoreDocs = true
        var docQuery: Query!
        if eventMedias.isEmpty {
            docQuery = self.eventsDataCollection.document(currentEventID).collection("eventMedias").order(by: "savesCount", descending: true).limit(to: 20)
        } else if let lastDocQuery = self.lastDocQuery {
            docQuery = self.eventsDataCollection.document(currentEventID).collection("eventMedias").order(by: "savesCount", descending: true).limit(to: 20).start(afterDocument: lastDocQuery)
        }
        
        if let docQuery = docQuery {
            print("GET DOCS")
            docQuery.getDocuments { (document, error) in
                if let documents = document?.documents {
                    var newEventMedias: [EventMedia] = []
                    for doc in documents {
                        if let media = try? doc.data(as: EventMedia.self) {
                            newEventMedias.append(media)
                        }
                    }
                    self.lastDocQuery = document?.documents.last
                    self.isFetchingMoreDocs = false
                    completion(newEventMedias)
                } else if let error = error {
                    print("Error getting updated event media: \(error)")
                    self.isFetchingMoreDocs = false
                    completion([])
                }
            }
        } else {
            self.isFetchingMoreDocs = false
            completion([])
        }
    }

As seen in my code, by utilizing:

.order(by: "savesCount", descending: true).limit(to: 20).start(afterDocument: lastDocQuery)

I am able to start exactly where I left off. I should also note that I am only calling this function if !isFetchingMoreDocs – otherwise the func will be called dozens of times in a matter of seconds while scrolling. The most important thing about this code is that I am checking lastDocQuery if it is nil. After the user scrolls all the way to the bottom, the lastDocQuery will no longer be valid and cause a fatal error. Also I am using a custom scroll view that tracks the scroll offset in order to fetch more media and make more calls to firebase.

Answered By – Trevor

Answer Checked By – Jay B. (BugsFixing Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *