繁体   English   中英

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

[英]Firestore Geohash Query with Live Updating Results in SwiftUI

我正在尝试在 SwiftUI 中构建一个 iOS 应用程序,用户可以在其中找到靠近其当前位置的“帖子”。 我有一个名为 Posts 的子集合,带有 geohash。 有点烦人的是,谷歌的这个库已无缘无故地存档https://github.com/firebase/geofire-objc 相反,我不得不使用这个库https://github.com/emilioschepis/swift-geohash

我找到当前用户周围的所有相邻 geohashes,然后针对每个以 geohash 开头并以 geohash + '~' 结尾的 geohash 运行针对 firstore 的查询。 这是我写的 function:

// 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 ,但它不喜欢“完成:”参数
  2. 如何确保在返回结果之前完成所有查询

您正在调用query.getDocuments ,它 获取数据一次 如果您还想获取该数据的更新,您应该使用addSnapshotListener ,它会在获取初始文档后侦听更新

为确保所有查询都已完成,您可以保留一个简单的计数器,每次调用addSnapshotListener回调时都会增加该计数器。 当计数器等于查询次数时,所有的查询都得到了服务器的响应。 这正是实时数据库的geofire-*库为其onReady事件所做的。

我对此进行了重构,它似乎可以实时工作和更新。 我不需要使用计数器,因为我将文档附加到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)
        }
    }
}

暂无
暂无

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

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