在SwiftUI中实时更新结果的Firestore Geohash查询

pnwntuvh  于 2023-02-03  发布在  Swift
关注(0)|答案(2)|浏览(141)

我正在尝试在SwiftUI中构建一个iOS应用程序,用户可以在其中找到他们当前位置附近的“帖子”。我有一个名为Posts with a geohash的子集合。有点烦人的是,谷歌的这个库无缘无故被归档为https://github.com/firebase/geofire-objc。相反,我不得不使用这个库https://github.com/emilioschepis/swift-geohash
我找到了当前用户周围所有相邻的geohash,然后针对firstore对每个geohash运行一个查询,以geohash开头,以geohash + '~'结尾。

// import https://github.com/emilioschepis/swift-geohash

class FirestorePosts: ObservableObject {
    
    @Published var items = [FirestorePost]() // Reference to our Model
      
    func geoPointQuery(tag:String){
        do {
            let db = Firestore.firestore().collection("tags")
            let docRef = db.document(tag).collection("posts")
            // users current location is "gcpu"
            let neighbors = try Geohash.neighbors(of: "gcpu", includingCenter: true)
            let queries = neighbors.map { bound -> Query in
                let end = "\(bound)~"
                return docRef
                    .order(by: "geohash")
                    .start(at: [bound])
                    .end(at: [end])
            }
            
            func getDocumentsCompletion(snapshot: QuerySnapshot?, error: Error?) -> () {
                guard let documents = snapshot?.documents else {
                    print("Unable to fetch snapshot data. \(String(describing: error))")
                    return
                }

                self.items += documents.compactMap { queryDocumentSnapshot -> FirestorePost? in
                    return try? queryDocumentSnapshot.data(as: FirestorePost.self)
                }
            }

            for query in queries {
                print("ran geo query")
                query.getDocuments(completion: getDocumentsCompletion)
            }
        }
        catch{
            print(error.localizedDescription)
        }
    }
}

到目前为止,查询工作正常,并按预期返回项目。但是,当Firestore发生变化时,结果不会实时更新。
1.我怎样才能使这个查询实时更新结果?我尝试添加query.addSnapshotListener,但它不喜欢“completion:“参数
1.如何确保在返回结果之前完成所有查询

mzmfm0qo

mzmfm0qo1#

你调用的是query.getDocuments,也就是gets data once,如果你还想获取数据的更新,你应该使用addSnapshotListener,它在获取初始文档后监听更新。
为了确保所有的查询都完成了,你可以保留一个简单的计数器,在每次调用addSnapshotListener回调时增加计数器的值。当计数器等于查询的数量时,所有的查询都从服务器得到了响应。这正是实时数据库的geofire-*库对它们的onReady事件所做的。

k75qkfdt

k75qkfdt2#

我对此进行了重构,它似乎可以实时工作和更新。我不需要使用计数器,因为我将文档附加到self.items(不确定这是否正确)。

...
for query in queries {
    query.addSnapshotListener { (querySnapshot, error) in
        guard let documents = querySnapshot?.documents else {
            print("No documents")
            return
        }
        
        self.items += documents.compactMap { queryDocumentSnapshot -> FirestorePost? in
            return try? queryDocumentSnapshot.data(as: FirestorePost.self)
        }
    }
}

相关问题