我有一个mapView,用户可以选择1英里,10英里,20英里和30英里的缩放半径,以从其设备所在的任何位置搜索餐厅。我已将所有餐厅的经纬度保存在GeoFire路径中。
当用户决定搜索时,首先获取用户的位置,然后让用户选择英里半径,然后将mapView缩放到该半径:
var selectedRadius = 0.0
let milesToMeters = 1609.344
let doubleDistance = 2 // according to this https://stackoverflow.com/a/5025970/4833705 to get a mapView radius of x miles, the distance needs to be doubled
var circleQuery: GFCircleQuery?
var queryHandle: UInt?
// 1. get the user's current location
guard let currentLocation = locationManager.location else { return }
let lat = currentLocation.coordinate.latitude
let lon = currentLocation.coordinate.longitude
let center = CLLocation(latitude: lat, longitude: lon)
// 2. user picks 10 mile radius
selectedRadius = (10 * doubleDistance) * milesToMeters
// 3. get the region I want to use for zoom in the mapView
let coordinateRegion = MKCoordinateRegionMakeWithDistance(center.coordinate, selectedRadius, selectedRadius)
mapView.setRegion(coordinateRegion, animated: true)
然后我想从GeoFire获得半径10英里范围内的所有餐厅,然后运行:
// 4. geoFire ref
let geofireRef = Database.database().reference().child("restaurant_locations")
let geoFire = GeoFire(firebaseRef: geofireRef)
// 5. since I had doubled the selectedRadius for the MKCoordinateRegionMakeWithDistance I now cut it in half to get the regular 10 mile radius in meters
let initialRadius = (selectedRadius / doubleDistance)
// 6. this is the radius I want to run the geoFire query on
circleQuery = geoFire?.query(at: center, withRadius: initialRadius)
// 7. observe .keyEntered at that query
queryHandle = circleQuery?.observe(.keyEntered, with: { (key: String!, location: CLLocation!) in ...
在步骤7中,当尝试观察.keyEntered
时出现异常:
“精度必须小于23!
然后,我尝试使用GeoFire的Region查询query(with:)
来设置跨度,但是抛出了完全相同的异常
let span = MKCoordinateSpanMake(initialRadius, initialRadius)
let region = MKCoordinateRegionMake(center.coordinate, span)
geoFire.query(with: region).observe(.keyEntered, with: { (key: String!, location: CLLocation!) in ...
选择10英里,20或30英里的MapView缩放半径时,如何运行GeoFire查询以匹配该半径?
答案 0 :(得分:0)
我对海里给出的旧答案在地图上显示了错误的距离。
正确的方法是前往double the number of miles you want to span then multiple that by 1609.344(1英里为1609.344米),并将结果设置为CLLocationDistance
以及您在MKCoordinateRegionMakeWithDistance()
内的位置(下面的步骤3)
使用GFRegionQuery
(下面的步骤6)代替GFCircleQuery
来使用geoFire
区域
基本上只是在下面的步骤2中进行转换,使用下面的步骤3中的区域,并将其设置为下面的步骤6中要使用的区域。
var radiusConversion = 0.0
let milesToMeters = 1609.344
let doubleDistance = 2
var regionQuery: GFRegionQuery?
var queryHandle: UInt?
// 1. get the user's current location
guard let currentLocation = locationManager.location else { return }
let lat = currentLocation.coordinate.latitude
let lon = currentLocation.coordinate.longitude
let center = CLLocation(latitude: lat, longitude: lon)
// 2. user picks 10 mile radius and do the conversion based on this link https://stackoverflow.com/a/5025970/4833705
radiusConversion = (10 * doubleDistance) * milesToMeters
// 3. set the region I want to use for zoom in the mapView
let region = MKCoordinateRegionMakeWithDistance(center.coordinate, radiusConversion, radiusConversion)
mapView.setRegion(region, animated: true) // zoom
// 4. geoFire ref
let geoFireRef = Database.database().reference().child("restaurant_locations")
let geoFire = GeoFire(firebaseRef: geoFireRef)
// 6. use GeoFire's query(with: region) and this is the radius I want to run the geoFire query on
regionQuery = geoFire.query(with: region)
// 7. observe.keyEntered at that region query
queryHandle = regionQuery?.observe(.keyEntered, with: {.observe(.keyEntered, with: { (key: String!, location: CLLocation!) in ...
// 8.
regionQuery?.observeReady {
// do something when the observer from step 7 is finished
}