7

The app I am building requires me to ask the user his location, autocomplete, and to make sure that he is indeed nearby. So my idea is to use Google Places Autocomplete, and return the result in a UITableView.

To make sure that the user is near the place he is typing, I want to set the GMSCoordinatesBound to be a certain radius around the user's current location. I know how to get the user's location through CoreLocation, however I am not sure how to convert these coordinates to a GMSCoordinateBounds object that I can use in Google Places autocompleteQuery. Can anybody give me a hint?

Thanks!

Charles Panel
  • 255
  • 2
  • 10

3 Answers3

10

My two cents.

extension GMSCoordinateBounds {
    convenience init(location: CLLocationCoordinate2D, radiusMeters: CLLocationDistance) {
        let region = MKCoordinateRegionMakeWithDistance(location, radiusMeters, radiusMeters)
        self.init(coordinate: region.northWest, coordinate: region.southEast)
    }
}

extension MKCoordinateRegion {
    var northWest: CLLocationCoordinate2D {
        return CLLocationCoordinate2D(latitude: center.latitude + span.latitudeDelta / 2, longitude: center.longitude - span.longitudeDelta / 2)
    }

    var southEast: CLLocationCoordinate2D {
        return CLLocationCoordinate2D(latitude: center.latitude - span.latitudeDelta / 2, longitude: center.longitude + span.longitudeDelta / 2)
    }
}

Using

let bounds = GMSCoordinateBounds(location: coordinate, radiusMeters: 20000)
Arsonik
  • 2,276
  • 1
  • 16
  • 24
9

You are now able to restrict the bounds for which the Google Autocomplete ViewController searches. See here: https://developers.google.com/places/ios-api/autocomplete#set_the_gmscoordinatebounds_of_autocomplete

Specifically, you can use CLLocationManager to get your lat and long. Then add offsets to get the bounding region of a map area.

You can do this without having a map in your view. For the case when you are adding an address to a field, for example.

Use https://developers.google.com/places/ios-api/autocomplete#add_a_full-screen_control to setup the full screen search. But add (Swift 2) this code in an IBAction that activates the search autocomplete:

let manager = CLLocationManager()
        manager.startUpdatingLocation()
        let lat = manager.location!.coordinate.latitude
        let long = manager.location!.coordinate.longitude
let offset = 200.0 / 1000.0;
        let latMax = lat + offset;
        let latMin = lat - offset;
let lngOffset = offset * cos(lat * M_PI / 200.0);
        let lngMax = long + lngOffset;
        let lngMin = long - lngOffset;
let initialLocation = CLLocationCoordinate2D(latitude: latMax, longitude: lngMax)
let otherLocation = CLLocationCoordinate2D(latitude: latMin, longitude: lngMin)    
let bounds = GMSCoordinateBounds(coordinate: initialLocation, coordinate: otherLocation)

    let autocompleteController = GMSAutocompleteViewController()

    autocompleteController.autocompleteBounds = bounds
    autocompleteController.delegate = self
    self.presentViewController(autocompleteController, animated: true, completion: nil)

I figured this out with help from the Google Docs and this post: Moving a CLLocation by x meters

Adjust the parameters per the post to change your bounding region. Now I get local search results, not the default New York and beyond.

This assumes you have the Google Places API for iOS set up properly. And, your Google iOS API Key installed (in AppDelegate), the Google client installed and the AutoCompleteViewControllerDelegate extension in your ViewController.

Community
  • 1
  • 1
D. Rothschild
  • 659
  • 9
  • 14
  • Note that this is still setting a **bias**, not a **restriction** (as I explain in my answer). – spiv Feb 12 '16 at 04:41
  • I interpret the original question as needing a bias, not a absolute restriction. I think a wider user case is the bias, as you call it, search around this area...but not restricted to this area. This is very little information on Stackoverflow (that I could find), that gives advice on how to get the bias and not live with the default in the API docs. Thanks for reviewing. – D. Rothschild Feb 12 '16 at 18:21
  • autocompleteBounds has been deprecated. It appears that you now need to use a GMSAutocompleteFilter() with a location bias to achieve the same result. Use the same bounds described above then try: let filter = GMSAutocompleteFilter() filter.type = .address filter.locationBias = bounds as? GMSPlaceLocationBias autocompleteController.autocompleteFilter = filter – D. Rothschild Oct 24 '21 at 02:26
2

First, some clarifications about what's possible:

  1. The bounds you give to autocomplete will strongly bias the results to be in or near that area, but it's not a hard limit. Users can still type Eiffel Tower, Franc and select the Eiffel Tower in Paris, France even if the location is New Zealand.
  2. The autocomplete bounds are a rectangle, not a circle, so to be pedantic you can't bias to a radius. But a rectangle with the corners a certain distance away from the center will work just fine.

You can offset your coordinate by a fixed distance to make new coordinates for the northeast and southwest corners, e.g. by using https://stackoverflow.com/a/7278293/806600 (answer to "Moving a CLLocation by x meters").

You can then construct a GMSCoordinateBounds from a CLLocationCoordinate2D with those:

GMSCoordinateBounds *bounds = 
  [[GMSCoordinateBounds alloc] initWithCoordinate:northEast
                                       coordinate:southWest];

And then pass that to autocompleteQuery.

Community
  • 1
  • 1
spiv
  • 2,458
  • 1
  • 16
  • 20
  • Thanks for that detailed response. I have one follow-up question: is there a way to completely restrict the area, since bounds is just a bias? – Charles Panel Aug 27 '15 at 10:26
  • 1
    No, there's no way to completely restrict the area. (The Google Places API webservice allows you to limit autocomplete results to a particular country via `&components=country:us`, but the iOS flavour of the Google Places API doesn't have this feature). – spiv Sep 08 '15 at 05:31
  • A small update on my Sept 2015 comment: the iOS flavour now supports a country filter too: https://developers.google.com/places/ios-api/reference/interface_g_m_s_autocomplete_filter.html – spiv Mar 31 '16 at 03:38