Swift 如何从地理查询中获取文档?
我将此函数用于地理查询。但我不知道如何将查询中的文档添加到数组中。因此,我可以使用Firestore文档中的信息显示一些地图注释。我应该如何改变它Swift 如何从地理查询中获取文档?,swift,google-cloud-firestore,geofire,Swift,Google Cloud Firestore,Geofire,我将此函数用于地理查询。但我不知道如何将查询中的文档添加到数组中。因此,我可以使用Firestore文档中的信息显示一些地图注释。我应该如何改变它 func geoQuery() { // [START fs_geo_query_hashes] // Find cities within 50km of London let center = CLLocationCoordinate2D(latitude: 51.5074, longitu
func geoQuery() {
// [START fs_geo_query_hashes]
// Find cities within 50km of London
let center = CLLocationCoordinate2D(latitude: 51.5074, longitude: 0.1278)
let radiusInKilometers: Double = 50
// 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: radiusInKilometers)
let queries = queryBounds.compactMap { (any) -> Query? in
guard let bound = any as? GFGeoQueryBounds else { return nil }
return db.collection("cities")
.order(by: "geohash")
.start(at: [bound.startValue])
.end(at: [bound.endValue])
}
var matchingDocs = [QueryDocumentSnapshot]()
// 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 <= radiusInKilometers {
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)
}
// [END fs_geo_query_hashes]
}
func地理查询(){
//[启动fs\u geo\u查询\u散列]
//查找距离伦敦50公里以内的城市
设中心=CLLOCATIONCOORDIATE2D(纬度:51.5074,经度:0.1278)
let radiusInKilometers:Double=50
//“bounds”中的每一项都代表一个startAt/endAt对。我们必须发出
//每对的单独查询。最多可以有9对边界
//取决于重叠,但在大多数情况下有4个。
让queryBounds=GFUtils.queryBounds(对于位置:center,
withRadius:半径(公里)
让querys=queryBounds.compactMap{(任意)->Query?在
guard let bound=any as?GFGeoQueryBounds else{return nil}
返回数据库集合(“城市”)
.订单(由“geohash”填写)
.start(位于:[bound.startValue])
.end(位于:[bound.endValue])
}
var matchingDocs=[QueryDocumentSnapshot]()
//将所有查询结果收集到一个列表中
func getDocumentsCompletion(快照:QuerySnapshot?,错误:error?)->(){
guard let documents=snapshot?.其他文档{
打印(“无法获取快照数据。\(字符串(描述:错误)))
返回
}
用于文档中的文档{
将lat=document.data()[“lat”]设为双精度??0
将lng=document.data()[“lng”]设为双精度??0
让坐标=CLLocation(纬度:纬度,经度:lng)
设centerPoint=CLLocation(纬度:center.lation,经度:center.longitude)
//由于GeoHash的准确性,我们必须过滤掉一些误报,但是
//大多数都会匹配
让距离=GFUtils.distance(从:中心点到:坐标)
如果距离这是我在结构中的Pin模型:
struct Pin: Identifiable {
var id = UUID().uuidString
var location: MKCoordinateRegion
var name: String
var img: String
}
然后我将使用地理查询功能:
func geoQuery() {
// [START fs_geo_query_hashes]
// Find cities within 50km of London
let center = CLLocationCoordinate2D(latitude: 51.5074, longitude: 0.1278)
let radiusInKilometers: Double = 50
// 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: radiusInKilometers)
let queries = queryBounds.compactMap { (any) -> Query? in
guard let bound = any as? GFGeoQueryBounds else { return nil }
return db.collection("cities")
.order(by: "geohash")
.start(at: [bound.startValue])
.end(at: [bound.endValue])
}
var matchingDocs = [QueryDocumentSnapshot]()
// 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 name = document.data()["names"] as? String ?? "no name"
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 <= radiusInKilometers {
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)
}
// [END fs_geo_query_hashes]
}
func地理查询(){
//[启动fs\u geo\u查询\u散列]
//查找距离伦敦50公里以内的城市
设中心=CLLOCATIONCOORDIATE2D(纬度:51.5074,经度:0.1278)
let radiusInKilometers:Double=50
//“bounds”中的每一项都代表一个startAt/endAt对。我们必须发出
//每对的单独查询。最多可以有9对边界
//取决于重叠,但在大多数情况下有4个。
让queryBounds=GFUtils.queryBounds(对于位置:center,
withRadius:半径(公里)
让querys=queryBounds.compactMap{(任意)->Query?在
guard let bound=any as?GFGeoQueryBounds else{return nil}
返回数据库集合(“城市”)
.订单(由“geohash”填写)
.start(位于:[bound.startValue])
.end(位于:[bound.endValue])
}
var matchingDocs=[QueryDocumentSnapshot]()
//将所有查询结果收集到一个列表中
func getDocumentsCompletion(快照:QuerySnapshot?,错误:error?)->(){
guard let documents=snapshot?.其他文档{
打印(“无法获取快照数据。\(字符串(描述:错误)))
返回
}
用于文档中的文档{
将lat=document.data()[“lat”]设为双精度??0
将lng=document.data()[“lng”]设为双精度??0
让name=document.data()[“names”]作为字符串??“无名称”
让坐标=CLLocation(纬度:纬度,经度:lng)
设centerPoint=CLLocation(纬度:center.lation,经度:center.longitude)
//由于GeoHash的准确性,我们必须过滤掉一些误报,但是
//大多数都会匹配
让距离=GFUtils.distance(从:中心点到:坐标)
如果距离我不知道文档是如何构造的,也不知道地图是如何配置为显示数据的(例如,注释与区域),但解决此问题的一般方法是协调函数中的查询循环,并为它们提供一个完成处理程序。为此,我们可以使用分派组。在该组的完成处理程序中,您有一个文档快照数组,需要循环通过该数组来获取数据(来自每个文档),构造Pin
,并将其添加到地图中。此处涉及的许多其他步骤我无法帮助您,因为我不知道您的文档和地图是如何配置的,但这将对您有所帮助。也就是说,您可以稍微减少此代码并使其更高效,但我们还是使用您正在使用的Firebase示例代码吧首先让它工作
struct Pin: Identifiable {
let id = UUID().uuidString
var location: MKCoordinateRegion
var name: String
var img: String
}
func geoQuery() {
// [START fs_geo_query_hashes]
// Find cities within 50km of London
let center = CLLocationCoordinate2D(latitude: 51.5074, longitude: 0.1278)
let radiusInKilometers: Double = 50
// 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: radiusInKilometers)
let queries = queryBounds.compactMap { (Any) -> Query? in
guard let bound = Any as? GFGeoQueryBounds else { return nil }
return db.collection("cities")
.order(by: "geohash")
.start(at: [bound.startValue])
.end(at: [bound.endValue])
}
// Create a dispatch group outside of the query loop since each iteration of the loop
// performs an asynchronous task.
let dispatch = DispatchGroup()
var matchingDocs = [QueryDocumentSnapshot]()
// 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))")
dispatch.leave() // leave the dispatch group when we exit this completion
return
}
for document in documents {
let lat = document.data()["lat"] as? Double ?? 0
let lng = document.data()["lng"] as? Double ?? 0
let name = document.data()["names"] as? String ?? "no name"
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 <= radiusInKilometers {
matchingDocs.append(document)
}
}
dispatch.leave() // leave the dispatch group when we exit this completion
}
// 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 {
dispatch.enter() // enter the dispatch group on each iteration
query.getDocuments(completion: getDocumentsCompletion)
}
// [END fs_geo_query_hashes]
// This is the completion handler of the dispatch group. When all of the leave()
// calls equal the number of enter() calls, this notify function is called.
dispatch.notify(queue: .main) {
for doc in matchingDocs {
let lat = doc.data()["lat"] as? Double ?? 0
let lng = doc.data()["lng"] as? Double ?? 0
let name = doc.data()["names"] as? String ?? "no name"
let coordinates = CLLocation(latitude: lat, longitude: lng)
let region = MKCoordinateRegion(center: <#T##CLLocationCoordinate2D#>, latitudinalMeters: <#T##CLLocationDistance#>, longitudinalMeters: <#T##CLLocationDistance#>)
let pin = Pin(location: region, name: name, img: "someImg")
// Add pin to array and then to map or just add pin directly to map here.
}
}
}
struct Pin:可识别{
设id=UUID().UUIString
变量位置:MKCoordinateRegion
变量名称:String
var-img:String
}
func geoQuery(){
//[启动fs\u geo\u查询\u散列]
//查找距离伦敦50公里以内的城市
设中心=CLLOCATIONCOORDIATE2D(纬度:51.5074,经度:0.1278)
let radiusInKilometers:Double=50
//“bounds”中的每一项都代表一个startAt/endAt对。我们必须发出
//每对的单独查询。最多可以有9对边界
//取决于重叠,但在大多数情况下有4个。
让queryBounds=GFUtils.queryBounds(对于位置:center,
withRadius:半径(公里)
让querys=queryBounds.compactMap{(任意)->Query?在
guard let bound=Any as?GFGeoQueryBounds else{return nil}
返回数据库集合(“城市”)
.订单(由“geohash”填写)
Map(coordinateRegion: $region, interactionModes: .all, showsUserLocation: true, annotationItems: pvm.allPins) { pin in
MapAnnotation(coordinate: pin.location.coordinate) {
Image(pin.img)
}
}