Get list of nearby places with Google Places API - ios

I am working on a project which can fetch the list of nearby places (from my current place). I use Google Places API and what I have tried is shown below. I see new view which has a mapview with mark position of most prominent places and table which contains list of these places. I need to fetch list of the places so that I can render it on my tableview.
- (IBAction)pickPlace:(UIButton *)sender {
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(51.5108396, -0.0922251);
CLLocationCoordinate2D northEast = CLLocationCoordinate2DMake(center.latitude + 0.001, center.longitude + 0.001);
CLLocationCoordinate2D southWest = CLLocationCoordinate2DMake(center.latitude - 0.001, center.longitude - 0.001);
GMSCoordinateBounds *viewport = [[GMSCoordinateBounds alloc] initWithCoordinate:northEast coordinate:southWest];
GMSPlacePickerConfig *config = [[GMSPlacePickerConfig alloc] initWithViewport:viewport];
_placePicker = [[GMSPlacePicker alloc] initWithConfig:config];
[_placePicker pickPlaceWithCallback:^(GMSPlace *place, NSError *error) {
if (error != nil) {
NSLog(#"Pick Place error %#", [error localizedDescription]);
return;
}
if (place != nil) {
NSLog(#"Place name %#", place.name);
NSLog(#"Place address %#", place.formattedAddress);
NSLog(#"Place attributions %#", place.attributions.string);
} else {
NSLog(#"No place selected");
}
}];
}

Then you shouldn't use GMSPlacePicker, because it offers the UI to you for your user to make a single selection. If you want a list of places that you can display yourself then you should use the REST interface provided by google to get the required details and update your UI.

It is doable to get list of nearby places (from my current place) with Google Places API. I used the following method to achieve the same:
[GMSPlaceClient currentPlaceWithCallback:]
An array of nearby places with likelihood is returned.

Related

How to integrate Google Map in Objective c?

I am new to iOS and have to show Google Map having two restaurant locations with different lat and long in Los Angeles area. I need to make sure if user clicks on map it will allow user to get directions to that specific restaurant. So if all locations are on one map, user would need to click on desired restaurant/pin on map and get directions - correct?
try this I found it before
In -(void)mapView:(GMSMapView *)mapView didTapInfoWindowOfMarker:(GMSMarker *)marker// This method will get call after taping marker pin(GMSMapView map view delegate method).
{ get the latitude and longitude of that marker.
}
Take the latitude and longitude of current location
Now Draw route between two location
//Download LRouteController from this link https://github.com/lukagabric/LRouteController
//This will draw link between two co-ordinate
//In .h File declare LRouteController *_routeController;
if ([_coordinates count] > 1)
{
//Draw line between two co-ordinate
[_routeController getPolylineWithLocations:_coordinates travelMode:TravelModeDriving andCompletitionBlock:^(GMSPolyline *polyline, NSError *error) {
if (error)
{
NSLog(#"%#", error);
}
else if (!polyline)
{
NSLog(#"No route");
[_coordinates removeAllObjects];
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"No route" message:#"No route available for this route." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
else
{
//Drow route
_markerStart.position = [[_coordinates objectAtIndex:0] coordinate];
_markerStart.map = googleMapview;
_markerFinish.position = [[_coordinates lastObject] coordinate];
_markerFinish.map = googleMapview;
_polyline = polyline;
_polyline.strokeWidth = 3;
_polyline.strokeColor = [UIColor blueColor];
_polyline.map = googleMapview;
}
}];
}
//If you are unable to get taped pin latitude and longitude the you can use custom GMSMarker
Ex: #interface MapMarker : GMSMarker //Create new file of GMSMarker
#property (nonatomic, strong) coOrdinateData *data;(CoOrdinateData is NSObject class declare lat and long value)
#end
While adding marker on map use
MapMarker *marker= [[MapMarker alloc]init];
[marker setPosition:CLLocationCoordinate2DMake(LocationAtual.coordinate.latitude,LocationAtual.coordinate.longitude)];
marker.data=data;//Take lat and long value in object class and pass object class in marker object
After typing on map marker you can get value like
-(void)mapView:(GMSMapView *)mapView didTapInfoWindowOfMarker:(GMSMarker *)marker
{
NSString *strLat = ((MapMarker *)marker).data.lat ;
NSString *strLong = ((MapMarker *)marker).data.long ;
//Add both the current location and marker latitude and longitude in _coordinates and draw route.
}

currentplacewithcallback not being called in google place iOS api

I am trying to get current place based on google place API iOS, other API for place picker, add place is calling callback methods, but when i am trying to get current place with below code, it not giving any error or not even calling callback method.
_placesClient = [GMSPlacesClient sharedClient];
[_placesClient currentPlaceWithCallback:^(GMSPlaceLikelihoodList *likelihoodList, NSError *error) {
if (error != nil) {
NSLog(#"Current Place error %#", [error localizedDescription]);
return;
}
int cnt =0;
for (GMSPlaceLikelihood *likelihood in likelihoodList.likelihoods) {
cnt++;
if(cnt==1)
{
GMSPlace* place = likelihood.place;
NSLog(#"Current Place name %# at likelihood %g", place.name, likelihood.likelihood);
NSLog(#"Current Place address %#", place.formattedAddress);
NSLog(#"Current Place attributions %#", place.attributions);
NSLog(#"Current PlaceID %#", place.placeID);
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(place.coordinate.latitude,place.coordinate.longitude);
// CLLocationCoordinate2D center = CLLocationCoordinate2DMake([lat doubleValue],[lng doubleValue]);
CLLocationCoordinate2D northEast = CLLocationCoordinate2DMake(center.latitude + 0.001, center.longitude + 0.001);
CLLocationCoordinate2D southWest = CLLocationCoordinate2DMake(center.latitude - 0.001, center.longitude - 0.001);
GMSCoordinateBounds *viewport = [[GMSCoordinateBounds alloc] initWithCoordinate:northEast
coordinate:southWest];
GMSPlacePickerConfig *config = [[GMSPlacePickerConfig alloc] initWithViewport:viewport];
_placePicker = [[GMSPlacePicker alloc] initWithConfig:config];
[_placePicker pickPlaceWithCallback:^(GMSPlace *place, NSError *error) {
if (error != nil) {
NSLog(#"Pick Place error %#", [error localizedDescription]);
}
if (place != nil) {
[_placesClient reportDeviceAtPlaceWithID:place.placeID];
NSLog(#"Place name %#", place.name);
NSLog(#"Place address %#", place.formattedAddress);
NSLog(#"Place placeID %#", place.placeID);
NSLog(#"Place number %#", place.phoneNumber);
NSLog(#"Place website %#", place.website);
self.placeInfo = [[SHPlaceInfo alloc]init];
self.placeInfo.address=place.formattedAddress;
self.placeInfo.phnNumber=place.phoneNumber;
self.placeInfo.website = [NSString stringWithFormat:#"%#",place.website];
self.placeInfo.idStr = place.placeID;
self.placeInfo.lat =[NSString stringWithFormat:#"%f", place.coordinate.latitude];
self.placeInfo.lng =[NSString stringWithFormat:#"%f", place.coordinate.longitude];
self.placeInfo.type = [place.types componentsJoinedByString:#","];
self.placeInfo.name = place.name;
[self savePlaceDatainDatabase:self.placeInfo];
// [self getNearDetailPlaces];
//if place id gives phone number then need to use below flow and remove api call above getNearDetailPlaces
selectedPlaceDetailViewController *placeDetailVC=[self.storyboard instantiateViewControllerWithIdentifier:#"selectedPlaceDetailViewController"];
placeDetailVC.placeInfo = self.placeInfo;
placeDetailVC.strCalledFromPage=#"Home";
[self.navigationController pushViewController: placeDetailVC animated:YES];
} else {
NSLog(#"No place selected");
}
}];
}
}
}];
One possibility: you might not be retaining a reference to _placesClient.
The outstanding callback alone won't keep the GMSPlacesClient instance alive, so if you don't ensure your program keeps a reference to it the callback might never be fired, which matches the symptom you see.
I am not sure with exact issue, but after running this in iPhone6 its calling that callback method,it can be issue of OS version also.Google Place API for iOS is only supported in latest version of OS.and i have got this spark from #ZeMoon's answer.
Thank you all for reply
I had the same issue, and just like you it seems to work only on iPhone 6 simulator and up, so it is probably due to the assumed iOS version on the simulated devices.

reverseGeocodeLocation Only Executes Completion Block Once

I have an array of coordinates that I step through with a for loop. I would like to place annotations on a map for each location and have the subtitle for the callout be the address of the coordinate, found by using reverseGeocodeLocation In the for loop, I call the reverseGeocodeLocation method, and inside the completion block I create the annotation and display it on the map. However, when I run the app, only one annotation shows up. I went in the debugger, and the completion block is only getting called once (for two calls to the reverseGeocodeLocation method). Any suggestions to fix this?
My for loop:
for(int i = 0; i < [locations count]; i++)
{
CLLocation *location = [locations objectAtIndex:i];
__block NSString *info;
NSLog(#"Resolving the Address");
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error)
{
NSLog(#"Found placemarks: %#, error: %#", placemarks, error);
if (error == nil && [placemarks count] > 0)
{
placemark = [placemarks lastObject];
info = [NSString stringWithFormat:#"%# %# %# %#, %#",
placemark.subThoroughfare, placemark.thoroughfare,
placemark.postalCode, placemark.locality,
placemark.administrativeArea];
[self remainderOfMethod:location withAddress:info atIndex:i];
}
else
{
NSLog(#"%#", error.debugDescription);
}
} ];
}
And the method called at the completion block:
- (void) remainderOfMethod: (CLLocation *)location withAddress:(NSString *)info atIndex: (int)i
{
MKPointAnnotation* annotation = [[MKPointAnnotation alloc] init];
if (location != nil)
{
[annotation setSubtitle:[NSString stringWithFormat:#"%#", info]];
annotation.coordinate = location.coordinate;
[self.mapView addAnnotation:annotation];
}
}
Thanks!
From the official Apple documentation:
After initiating a reverse-geocoding request, do not attempt to
initiate another reverse- or forward-geocoding request
You can find the docs here: https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLGeocoder_class/Reference/Reference.html#//apple_ref/occ/instm/CLGeocoder/reverseGeocodeLocation:completionHandler:
One way to solve it is to do only one request at a time in a recursive method that pops a location from a stack (or array) on each iteration.
Even in that case, consider what Apple has to say about it:
Geocoding requests are rate-limited for each app, so making too many
requests in a short period of time may cause some of the requests to
fail
So you may want to request geocoding on demand, for example when a user taps on an annotation.

iOS maps show the center of a specific city

I am using MapKit and CoreLocation to find the users location and then display it on a map.
I am using this code to display the City and State (which is what I am interested in, not the EXACT location).
// this delegate is called when the app successfully finds your current location
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
[geocoder reverseGeocodeLocation:self.locationManager.location
completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(#"reverseGeocodeLocation:completionHandler: Completion Handler called!");
if (error){
NSLog(#"Geocode failed with error: %#", error);
return;
}
CLPlacemark *placemark = [placemarks objectAtIndex:0];
CLLocationCoordinate2D zoomLocation;
zoomLocation.latitude = placemark.region.center.latitude;
zoomLocation.longitude= placemark.region.center.longitude;
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, METERS_PER_MILE * 2, METERS_PER_MILE * 2);
[self.mapView setRegion:viewRegion animated:NO];
NSString *location = [NSString stringWithFormat:#"%#, %#", placemark.locality, placemark.administrativeArea];
NSLog(#"%#", location);
}];
}
This works great, but what I really want to do is zoom in to the center of the city itself, not the users location.
Is there some kind of property I can access to do this?
Otherwise, is anyone aware of a work around? That would be great, thanks!
not directly. There is no api like MKGetClosestCapitalTo(userLocation)
BUT
you can use the user's location for reverse geocoding and THEN use the city name to geocode the address => that will get you the city center.
so:
address = reversegeocode(userLocation)
loc = geocode(address.cityName)
zoom map to that loc
(you already have 1 so just do 2 and 3 ;))
I would recommend Daij-Djan's approach of doing two geocodes to essentially "lose resolution" in the query. For example, if you find that the user is at a certain address in Austin, TX, then you would get just "Austin, TX" out of the results and ask for the coordinate of that. Then you will have the center of what Apple considers Austin.
Another approach might be to tie into an external database or API. For example, Wikipedia has a center coordinate for each city it contains that you might be able to query & use.
If you want to center around particular city, you can specify the coordinate of the city in following code and the map view will be centred around it.
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance("SPECIFY THE COORDINATE OF THE CITY YOU WANT TO CENTER AROUND HERE", 800, 800);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];

google search places autocomplete specific to country in ios

I am working on Google Places AutoComplete Service where i need to filter the places specific to country and found this.
It is working good untill when i pass a parameter components=country:se to filter the autocomplete field its response is REQUEST_DENIED
NSMutableString *url = [NSMutableString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/autocomplete/json?input=%#&components=country:se&sensor=%#&key=%#",
[input stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
SPBooleanStringForBool(sensor), key];
I need the autocomplete to give suggestion specific to country.
Thanks
This works fine for me.
You can set this by adding the bounds for the region by adding its extreme top left and bottom right location points of the the Geographical area.
like for USA i used.
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:CLLocationCoordinate2DMake(52.00, 148.00)
coordinate:CLLocationCoordinate2DMake(18.00, -71.00)];
GMSPlacesClient * placesClient = [[GMSPlacesClient alloc] init];
[placesClient autocompleteQuery:fieldValue bounds:bounds filter:nil
callback:^(NSArray *results, NSError *error)
{
if (error != nil)
{
NSLog(#"Autocomplete error %#", [error localizedDescription]);
return;
}
else
{
[self.autoComplete removeAllObjects];
[self.AddressPlaceID removeAllObjects];
for (GMSAutocompletePrediction* result in results)
{
CustomAddress * parseAddress = [[CustomAddress alloc] init];
NSString * adString = [parseAddress removeCountryFromAddress:result.attributedFullText.string];
[self.autoComplete addObject:adString];
[self.AddressPlaceID addObject:result.placeID];
}
[self.autoCompleteTable reloadData];
}
}];
But you can still get the other location results . It will prefer first the geographical bounds you define in the GMCoordinateBounds
Why do not use the iOS SDK to obtain country specific results? Follow this answer.

Resources