繁体   English   中英

我们如何在 ios swift 上对 firebase / firestore 查询进行分页?

[英]How can we paginate a firebase / firestore query on ios swift?

我试图找到一个解决方案,用于在 ios/swift 上对 firebase 查询进行分页,但我无法为我的状态构建算法。

我的方法是这样的:

func downloadData(completion: @escaping ([Post]) -> Void) {
        
        // download data with pagination
        
        let firestoreDatabase = Firestore.firestore()
        
        var first =  firestoreDatabase.collection("posts").order(by: "date", descending: true).limit(to: 5)
        
        first.addSnapshotListener{ snapshot, error in
            
            guard let snapshot = snapshot else {
                print("Error retrieving cities: \(error.debugDescription)")
                return
            }
            
            guard let lastSnapshot = snapshot.documents.last else {
                // The collection is empty.
                return
            }
            
            self.postList.removeAll(keepingCapacity: false)
            
            DispatchQueue.global().async {
                
                for document in snapshot.documents {
                    
                    // getting data from document stuff ...
                    
                    self.postList.append(self.post)
                }
                
                completion(self.postList)
            }
            
            // how can I repeat this query as long as lastSnapshot exist
            firestoreDatabase.collection("posts").order(by: "date", descending: true).start(afterDocument: lastSnapshot).addSnapshotListener { querySnapshot, error in
            }
        }
}

我尝试了以下心态但没有用,并进入了无限循环。 我不明白这是为什么。

func downloadData(completion: @escaping ([Post]) -> Void) {
        
        // download data with pagination
        
        let firestoreDatabase = Firestore.firestore()
        
        var first =  firestoreDatabase.collection("posts").order(by: "date", descending: true).limit(to: 5)
        
        first.addSnapshotListener{ snapshot, error in
            
            guard let snapshot = snapshot else {
                print("Error retrieving cities: \(error.debugDescription)")
                return
            }
            
            guard let lastSnapshot = snapshot.documents.last else {
                // The collection is empty.
                return
            }
            
            self.postList.removeAll(keepingCapacity: false)
            
            DispatchQueue.global().async {
                
                for document in snapshot.documents {
                    
                    // geting data from document stuff ...
                    
                    self.postList.append(self.post)
                }
                
                completion(self.postList)
            }

            repeat {
                firestoreDatabase.collection("posts").order(by: "date", descending: true).start(afterDocument: lastSnapshot).addSnapshotListener { querySnapshot, error in
                    
                    guard let snapshot = snapshot else {
                        print("Error retrieving cities: \(error.debugDescription)")
                        return
                    }
                    
                    guard let lastSnapshot = snapshot.documents.last else {
                        // The collection is empty.
                        return
                    }
                    
                    self.postList.removeAll(keepingCapacity: false)
                    
                    DispatchQueue.global().async {
                        
                        for document in snapshot.documents {
                            
                            // getting data from document stuff ...
                            
                            self.postList.append(self.post)
                        }
                        
                        completion(self.postList)
                    }
                    
                    lastSnapshot = snapshot.documents.last
                }
            } while(lastSnapshot.exists)
        }
}

我认为 lastSnapshot 在查询循环之后必须为 nil,但它似乎仍然存在。

如何解决 lastSnapshot 问题? 还是有不同的心态/最简单的分页方法?

在 firebase 文档中,它说只使用它,但我们如何重复具有“.start(afterDocument: lastSnapshot)”内容的查询?

首先也是最重要的,对于普通的分页,在获取文档时不要使用快照监听器。 您可以使用快照侦听器对文档进行分页,但过程更加复杂。

为了清楚起见,我已将我的注释嵌入到下面代码的注释中。

let pageSize = 5
var cursor: DocumentSnapshot?

func getFirstPage(completion: @escaping (_ posts: [Post]?) -> Void) {
    let db = Firestore.firestore()
    let firstPage = db.collection("posts").order(by: "date", descending: true).limit(to: pageSize)
    
    firstPage.getDocuments { snapshot, error in
        guard let snapshot = snapshot else {
            // Don't leave the caller hanging on errors; return nil,
            // return a Result, throw an error, do something.
            completion(nil)
            if let error = error {
                print(error)
            }
            return
        }
        guard !snapshot.isEmpty else {
            // There are no results and so there can be no more
            // results to paginate; nil the cursor.
            cursor = nil
            
            // And don't leave the caller hanging, even on no
            // results; return an empty array.
            completion([])
            return
        }
        // Before parsing the snapshot, manage the cursor.
        if snapshot.count < pageSize {
            // This snapshot is smaller than a page size and so
            // there can be no more results to paginate; nil
            // the cursor.
            cursor = nil
        } else {
            // This snapshot is a full page size and so there
            // could potentially be more results to paginate;
            // set the cursor.
            cursor = snapshot.documents.last
        }
        var posts: [Post] = []
        
        for doc in snapshot.documents {
            posts.append(newPost) // pseudo code
        }
        completion(posts)
    }
}

func continuePages(completion: @escaping (_ posts: [Post]?) -> Void) {
    guard let cursor = cursor else {
        return
    }
    let db = Firestore.firestore()
    let nextPage = db.collection("posts").order(by: "date", descending: true).limit(to: pageSize).start(afterDocument: cursor)
    
    nextPage.getDocuments { snapshot, error in
        guard let snapshot = snapshot else {
            completion(nil)
            if let error = error {
                print(error)
            }
            return
        }
        guard !snapshot.isEmpty else {
            // There are no results and so there can be no more
            // results to paginate; nil the cursor.
            cursor = nil
            
            completion([])
            return
        }
        // Before parsing the snapshot, manage the cursor.
        if snapshot.count < pageSize {
            // This snapshot is smaller than a page size and so
            // there can be no more results to paginate; nil
            // the cursor.
            cursor = nil
        } else {
            // This snapshot is a full page size and so there
            // could potentially be more results to paginate;
            // set the cursor.
            cursor = snapshot.documents.last
        }
        var morePosts: [Post] = []
        
        for doc in snapshot.documents {
            morePosts.append(newPost) // pseudo code
        }
        completion(morePosts)
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM