Firebase GeoFire 关闭

Firebase GeoFire closure

我正在尝试使用 Firebase GeoFire,但关闭总是让我失望。 Firebase 在其文档中提供了这个示例代码片段

// After all callbacks have executed, matchingDocs contains the result. Note that this
// sample does not demonstrate how to wait on all callbacks to complete.
for query in queries {
    query.getDocuments(completion: getDocumentsCompletion)
}

不幸的是,它并没有展示我所需要的...

我希望它在预设的时间间隔内触发,所以我有这样的安排:

locationTimer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(getLocations), userInfo: nil, repeats: true)

那么我的代码与示例差不多:


var matchingDocs = [QueryDocumentSnapshot]()

@objc func getLocations() {
        let center = CLLocationCoordinate2D(latitude: lat, longitude: lon)
        let radiusInM: Double = 10000

        // Each item in 'bounds' represents a startAt/endAt pair. We have to issue
        // a separate query for each pair. There can be up to 9 pairs of bounds
        // depending on overlap, but in most cases there are 4.
        let queryBounds = GFUtils.queryBounds(forLocation: center,
                                              withRadius: radiusInM)
        let queries = queryBounds.map { bound -> Query in
            return db.collection("geopoints")
                .order(by: "geohash")
        }
        
        // Collect all the query results together into a single list
        func getDocumentsCompletion(snapshot: QuerySnapshot?, error: Error?) -> () {
            guard let documents = snapshot?.documents else {
                print("Unable to fetch snapshot data. \(String(describing: error))")
                return
            }

            for document in documents {
                let lat = document.data()["lat"] as? Double ?? 0
                let lng = document.data()["lng"] as? Double ?? 0
                let coordinates = CLLocation(latitude: lat, longitude: lng)
                let centerPoint = CLLocation(latitude: center.latitude, longitude: center.longitude)

                // We have to filter out a few false positives due to GeoHash accuracy, but most will match
                let distance = GFUtils.distance(from: centerPoint, to: coordinates)
            
                if distance <= radiusInM {
                    matchingDocs.append(document)
                }
            }
        }

        // After all callbacks have executed, matchingDocs contains the result. Note that this
        // sample does not demonstrate how to wait on all callbacks to complete.
        for query in queries {
            query.getDocuments(completion: getDocumentsCompletion)
        }
    }
}

等待回调完成并使用包含所有地理点的 matchingDocs 继续执行 getLocations() 函数之外的程序的正确方法是什么?感谢您的任何建议。

这是我的解决方案。只有在所有查询返回后才会调用完成的函数 allDone()。

// button press to read data from Firebase
@IBAction func getData(_ sender: Any) {
    getLocations(completion: {
           
    // code here to process all query results        
            
    })
}

func getLocations(completion: @escaping () -> Void) {
   let center = CLLocationCoordinate2D(latitude: lat, longitude: lon)
   let radiusInM: Double = 10000
        
   var queriesFinished = 0
        
   // Each item in 'bounds' represents a startAt/endAt pair. We have to issue
   // a separate query for each pair. There can be up to 9 pairs of bounds
   // depending on overlap, but in most cases there are 4.
   let queryBounds = GFUtils.queryBounds(forLocation: center,
                                         withRadius: radiusInM)
   let queries = queryBounds.map { bound -> Query in
       return db.collection("geopoints")
           .order(by: "geohash")
   }
        
   let numOfQueries = queries.count
        
   // Collect all the query results together into a single list
   func getDocumentsCompletion(snapshot: QuerySnapshot?, error: Error?) -> () {
       guard let documents = snapshot?.documents else {
           print("Unable to fetch snapshot data. \(String(describing: error))")
           return
       }
            
       for document in documents {
           let lat = document.data()["lat"] as? Double ?? 0
           let lng = document.data()["lng"] as? Double ?? 0
           let coordinates = CLLocation(latitude: lat, longitude: lng)
           let centerPoint = CLLocation(latitude: center.latitude, longitude: center.longitude)

           // We have to filter out a few false positives due to GeoHash accuracy, but most will match
          let distance = GFUtils.distance(from: centerPoint, to: coordinates)
            
           if distance <= radiusInM {
               matchingDocs.append(document)
           }
       }
            
       queriesFinished += 1
            
       allDone()
   }
        
   // After all callbacks have executed, matchingDocs contains the result. Note that this
   // sample does not demonstrate how to wait on all callbacks to complete.
   for query in queries {
       query.getDocuments(completion:getDocumentsCompletion)
   }
        
   func allDone() {
       if queriesFinished == numOfQueries {
           completion()
       }
   }
}

我在读到 async/await 可能是更好的方法,但我没有让它发挥作用。