I have a mapView and the users can choose a zoom radius of 1 mi, 10 mi, 20 mi, and 30 mi to search for restaurants from wherever their device is. I have all the restaurant's lat-lon saved inside a GeoFire path.
When the user decides to search, first I get the user/s location, then I let the user choose a mile radius, then I get the mapView to zoom to that radius:
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)
I then want to get all the restaurants in that 10 mile radius from GeoFire and I run:
// 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 ...
On step 7, when trying to observe the .keyEntered
I get the exception:
'Precision must be less than 23!
I then tried to set a span using GeoFire's Region query query(with:)
but I got the same exact exception thrown
let span = MKCoordinateSpanMake(initialRadius, initialRadius)
let region = MKCoordinateRegionMake(center.coordinate, span)
geoFire.query(with: region).observe(.keyEntered, with: { (key: String!, location: CLLocation!) in ...
When choosing a MapView zoom radius of 10 mi, 20, or 30 mi, how can I run a GeoFire query to match that radius?
The old answer I gave with the nautical miles showed the incorrect distance on the map.
The correct way is to double the number of miles you want to span then multiple that by 1609.344 (1 mile is 1609.344 meters) and set that result as the CLLocationDistance
s along with your location inside MKCoordinateRegionMakeWithDistance()
(step 3 below)
Use GFRegionQuery
(step 6 below) instead of a GFCircleQuery
to use the geoFire
region
Basically just do the conversion in step 2 below, use the region from step 3 below, and set it as the region to use in step 6 below.
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
}