Search on Google Map Sdk - ios

I need to implement the map view in my app to locate the required place. I had tried with the SVGeocoder concept.
[SVGeocoder geocode:searchfield.text
completion:^(NSArray *placemarks, NSHTTPURLResponse *urlResponse, NSError *error) {
}
But suppose I am trying to search any restaurent then the result is nil.
I was looking on Google map sdk but don't know how to do search functionality on GMSCameraPosition class.
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:latitude
longitude:longitude
zoom:5];
how to search with the address using google sdk.
Thanks in advance.

If I understood it correctly, you need the location co-ordinates from a address string. Its Forward geo-coding. You can take a look at Google's free api for this: Link1
You will need a API key from your google account to access this api and there is way to select a free or business plan depending on your number of requests.
You need to use a CLLocation object for getting co-ordinates from your address. I wrote a similar function. CLLocation* temp_location=[[CLLocation alloc]init];
temp_location=[GeoCoding findAddressCordinates:sourceAddressTxtField.text];
// Class GeoCoding to find Co-ordinates
#import <Foundation/Foundation.h>
#interface GeoCoding : NSObject {
}
+(CLLocation*)findAddressCordinates:(NSString*)addressString;
#end
#import "GeoCoding.h"
#import <CoreLocation/CLAvailability.h>
#implementation GeoCoding
+(CLLocation*)findAddressCordinates:(NSString*)addressString {
CLLocation *location;
NSString *url = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?address=%#&sensor=true", addressString];
url = [url stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
NSURL *wurl = [NSURL URLWithString:url];
NSData *data = [NSData dataWithContentsOfURL: wurl];
// Fail to get data from server
if (nil == data) {
NSLog(#"Error: Fail to get data");
}
else{
// Parse the json data
NSError *error;
NSDictionary *json = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions
error:&error];
// Check status of result
NSString *resultStatus = [json valueForKey:#"status"];
// If responce is valid
if ( (nil == error) && [resultStatus isEqualToString:#"OK"] ) {
NSDictionary *locationDict=[json objectForKey:#"results"] ;
NSArray *temp_array=[locationDict valueForKey:#"geometry"];
NSArray *temp_array2=[temp_array valueForKey:#"location"];
NSEnumerator *enumerator = [temp_array2 objectEnumerator];
id object;
while ((object = [enumerator nextObject])) {
double latitude=[[object valueForKey:#"lat"] doubleValue];
double longitude=[[object valueForKey:#"lng"] doubleValue];
location=[[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
NSLog(#"CLLocation lat is %f -------------& long %f",location.coordinate.latitude, location.coordinate.longitude);
}
}
}
return location;
}
#end
You can then use this co-ordinates in your Google Map to focus your camera position.

Related

How to get MKPolyline (Mapkit) using MBRoute (Mapbox)

I am developing two apps similar to Ola/Uber, a driver app and the other one is a rider app. The driver app uses mapbox for navigation while the rider app uses simple mapkit and google APIs. My problem starts when the driver re-routes while undergoing a ride and the rider app has to trace the driver's new path also. Right now the logic applied is as following: in didRerouteAlongRoute delegate of mapbox the driver app informs the server that it has re-routed along this particular MBRoute route. The server in turn informs and passes this information to the rider app. Problem is that this MBRoute data type is not usable at the rider end as it uses mapkit and not mapbox and I have to convert this information somehow so that I can make the same new route as the driver app using MKPolyline at the rider end. Any help is appreciated.
This api is being used at the rider end for making the route polyline originally: https://maps.googleapis.com/maps/api/directions/json
Finally I managed a way to accomodate the requirements. It includes the following 3 steps:
At the driver app (using the mapbox framework), in the didRerouteAlongRoute delegate, create an array containing the new route's latitude/longitude dictionaries like this:
-(void)navigationViewController:(MBNavigationViewController*)navigationViewController didRerouteAlongRoute:(MBRoute*)route{
CLLocationCoordinate2D *routeCoordinates = malloc(route.coordinateCount *sizeof(CLLocationCoordinate2D));
[route getCoordinates:routeCoordinates];
NSMutableArray *routeArray = [NSMutableArray new];
for (NSValue *value in route.coordinates) {
CLLocationCoordinate2D coordinate;
[value getValue:&coordinate];
NSDictionary *coDic = #{#"latitude" : [NSNumber numberWithDouble: coordinate.latitude],
#"longitude": [NSNumber numberWithDouble: coordinate.longitude]};
[routeArray addObject:coDic];
}
}
Then send this new route's information to the server through an API after serialising this array (reRouteJSONString) as following:
NSError *error;
NSString *reRouteJSONString = #"";
NSData *reRouteJSONData = [NSJSONSerialization dataWithJSONObject: routeArray options:NSJSONWritingPrettyPrinted error:&error];
reRouteJSONString = [[NSString alloc] initWithData: reRouteJSONData encoding:NSUTF8StringEncoding] ;
And now at the rider app, manipulate this information as following and form your new route polyline:
-(void)makeReroutePolyline:(NSString*)serialisedString{
MKMapView *mapView;
mapView.delegate = self;
NSError *jsonError;
NSData *objectData = [serialisedString dataUsingEncoding:NSUTF8StringEncoding];
NSArray *json = [NSJSONSerialization JSONObjectWithData:objectData options:NSJSONReadingMutableContainers error:&jsonError];
CLLocationCoordinate2D coordinates[json.count];
for (NSInteger index = 0; index < json.count; index++) {
CLLocationCoordinate2D coordinate = { [[json objectAtIndex:index][#"latitude"] doubleValue], [[json objectAtIndex:index][#"longitude"] doubleValue] };
coordinates[index] = coordinate;
}
MKPolyline *routeLine;
routeLine = [MKPolyline polylineWithCoordinates:coordinates count:json.count];
[mapView addOverlay:routeLine];
[mapView setVisibleMapRect:[routeLine boundingMapRect] edgePadding:UIEdgeInsetsZero animated:YES];
}

Show Location string using latitude and longitude

I am using this method to show the string of location using current location latitude and longitude but it is showing differently
NSString *urlString = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false",location.coordinate.latitude, location.coordinate.longitude];
NSError* error;
NSString *locationString = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString] encoding:NSASCIIStringEncoding error:&error];
NSData *data = [locationString dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSDictionary *dic = [[json objectForKey:#"results"] objectAtIndex:0];
NSArray* arr = [dic objectForKey:#"address_components"];
//Iterate each result of address components - find locality and country
NSString *cityName;
NSString *countryName;
for (NSDictionary* d in arr)
{
NSArray* typesArr = [d objectForKey:#"types"];
NSString* firstType = [typesArr objectAtIndex:0];
if([firstType isEqualToString:#"locality"])
cityName = [d objectForKey:#"long_name"];
if([firstType isEqualToString:#"country"])
countryName = [d objectForKey:#"long_name"];
}
NSString* locationFinal = [NSString stringWithFormat:#"%#,%#",cityName,countryName];
NSLog(#"Final Location %# ",locationFinal);
but final location is showing this type :-
Final Location नठदिलà¥à¤²à¥,India
Why it is showing this type? Can anyone know about this.
Please supply the language with the API params. If language is not supplied, the geocoder attempts to use the preferred language as specified in the Accept-Language header, or the native language of the domain from which the request is sent.
So please replace the code as with the language parameter as like this.
NSString *urlString = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false&language=en",location.coordinate.latitude, location.coordinate.longitude];
and try again.
I believe that is an uninitialzed variable which is pointing into random memory.
Try:
NSString *cityName = nil;
NSString *countryName = nil;
Short-circuit your for loop:
for (NSDictionary* d in arr)
{
// Add this after the existing code:
if (cityName && countryName)
break;
}
and check for errors before presenting the results:
if (cityName && countryName) {
NSString* locationFinal = [NSString stringWithFormat:#"%#,%#",cityName,countryName];
NSLog(#"Final Location %# ",locationFinal);
} else {
NSLog(#"Failed to find location");
}
Finally your JSON-processing code does no error-checking at all. That's a mistake.

Estimated Time Between two Locations in iOS [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
What is proper way to get ETA (estimated time arrival) from AnyLocation to MyCurrentLocation?
I want, when use tap on any annotation, then I have to set details on the Footer according to that annotation and user's current location.
Please see below image for better understanding.
I saw this What is proper way to get ETA (estimated time arrival) from any location to my current location and this calculate time taken to cover a journey in Apple Maps But they didn't solved my problem using this. I am getting always Null response using this. I put my code below:-
double latitude = -0.075410;
double longitude = 51.512520;
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:CLLocationCoordinate2DMake(latitude, longitude) addressDictionary:nil] ;
MKMapItem *mapItemSource = [[MKMapItem alloc] initWithPlacemark:placemark];
double latitude1 = -0.132128;
double longitude1 = 51.464138;
MKPlacemark *placemark1 = [[MKPlacemark alloc] initWithCoordinate:CLLocationCoordinate2DMake(latitude1, longitude1) addressDictionary:nil] ;
MKMapItem *mapItemDestination = [[MKMapItem alloc] initWithPlacemark:placemark1];
MKDirectionsRequest *directionsRequest = [[MKDirectionsRequest alloc] init];
[directionsRequest setSource:mapItemSource];
[directionsRequest setDestination:mapItemDestination];
directionsRequest.transportType = MKDirectionsTransportTypeAutomobile;
MKDirections *directions = [[MKDirections alloc] initWithRequest:directionsRequest];
[directions calculateETAWithCompletionHandler:^(MKETAResponse *response, NSError *error) {
if (error) {
NSLog(#"Error %#", error.description);
} else {
NSLog(#"expectedTravelTime %f", response.expectedTravelTime);
}
}];
//I am not sure why I am getting Null response into calculateETAWithCompletionHandler this method..
//Also tried following......
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
if (error) {
NSLog(#"Error %#", error.description);
} else {
MKRoute * routeDetails = response.routes.lastObject;
//[self.mapView addOverlay:routeDetails.polyline];
NSLog(#"Street %#",[placemark.addressDictionary objectForKey:#"Street"]);
NSLog(#"distance %#",[NSString stringWithFormat:#"%0.1f Miles", routeDetails.distance/1609.344]);
NSLog(#"expectedTravelTime %#",[NSString stringWithFormat:#"%0.1f minutes",routeDetails.expectedTravelTime/60]);
}
}];
//I am not sure why I am getting Null response into calculateDirectionsWithCompletionHandler this method..
Also I saw this Is there any way to determine the driving time between two locations using Apple's Maps API? and this How to calculate time required to complete the path in between two locations?. But RightNow, I don't want to use Google Maps Directions API. Because my client does not want to use that. If Google APIs are free, then Definitely I preferred that.
Also, I tried distanceFromLocation method. But, I think, This solution assumes straight-line distance between two points, which is almost never useful.
Is there any other solution for doing this..??
Any help would be appreciated.
Try this method. Here you have to pass source and destination latitude and longitude information.
NSString *strUrl = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%f,%f&sensor=false&mode=%#", lat, longi, userLat, userLong, #"DRIVING"];
NSURL *url = [NSURL URLWithString:[strUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSData *jsonData = [NSData dataWithContentsOfURL:url];
if(jsonData != nil)
{
NSError *error = nil;
id result = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
NSMutableArray *arrDistance=[result objectForKey:#"routes"];
if ([arrDistance count]==0) {
NSLog(#"N.A.");
}
else{
NSMutableArray *arrLeg=[[arrDistance objectAtIndex:0]objectForKey:#"legs"];
NSMutableDictionary *dictleg=[arrLeg objectAtIndex:0];
NSLog(#"%#",[NSString stringWithFormat:#"Estimated Time %#",[[dictleg objectForKey:#"duration"] objectForKey:#"text"]]);
}
}
else{
NSLog(#"N.A.");
}
If you want to calculate the travel time between points you first need to specify if you want driving or walking directions, and then generate directions. The result of the directions request will include a travel time estimate.
You'll need to use MapKit, MKDirectionsRequest, and MKDirections classes, among others. You'll also need to configure your app to ask Apple for permission to generate driving directions. I found this link online that explains how to calculate driving directions.
you can use google api for that and one more thing by default there is method
locA = [[CLLocation alloc] initWithLatitude:[[latsArray objectAtIndex:0] floatValue] longitude:[[longArray objectAtIndex:0] floatValue]];
locB = [[CLLocation alloc] initWithLatitude:[[latsArray objectAtIndex:1] floatValue] longitude:[[longArray objectAtIndex:1] floatValue]];
distance = [locA distanceFromLocation:locB] * 0.000621371;
and time for walk
float time = distance / 3.1; //divide by 3.1 for by walk

Attempting to drop pins based on MKMap from values from array

As the question says I am trying to add pins to my map based on the coordinates returned by my php file. Said file returns the following results
[{"dogid":"1","latitude":"15.435786","longitude":"-21.318447"},{"dogid":"1","latitude":"14.00000","longitude":"-18.536711"}]
What I am doing (well I believe i am) is taking the values from the link and saving them to a string. Secondly, save that string value to an array. Then, I go thru this array and save out the latitude and longitude and assign it to CLLocationCordinate 2dcoord. After whch I expect both pins to be dropped on whatever location they received.
However, what occurs is: Upon running the program, when it arrives on this lin
for (NSDictionary *row in locations) {
the loop is not run to assign the values, and it jumps to the end. Oddly, a single pin is dropped on the map (thou location doesnt appear to be the values that it waas passed).
Would appreciate a little incite into the matter.
Thanks
- (void)viewDidAppear:(BOOL)animated
{
NSMutableArray *annotations = [[NSMutableArray alloc] init];
NSURL *myURL =[NSURL URLWithString:#"link.php"];
NSError *error=nil;
NSString *str=[NSString stringWithContentsOfURL:myURL encoding:NSUTF8StringEncoding error:&error];
CLLocationCoordinate2D coord;
NSArray *locations=[NSArray arrayWithContentsOfFile:str];
for (NSDictionary *row in locations) {
NSNumber *latitude = [row objectForKey:#"latitude"];
NSNumber *longitude = [row objectForKey:#"longitude"];
// NSString *title = [row objectForKey:#"title"];
//Create coordinates from the latitude and longitude values
coord.latitude = latitude.doubleValue;
coord.longitude = longitude.doubleValue;
}
MKPointAnnotation *pin = [[MKPointAnnotation alloc] init];
pin.coordinate = coord;
[self.mapView addAnnotation:pin];
}
It looks like you are trying to save api response to and Array.
Api always returns json string which is NSString.
You need to convert decode json string.
In your case
NSString *str=[NSString stringWithContentsOfURL:myURL encoding:NSUTF8StringEncoding error:&error];
you need to decode str with [NSJSONSerialization JSONObjectWithData:<#(NSData )#> options:<#(NSJSONReadingOptions)#> error:<#(NSError *)#>] which give you proper array of dictionary.
Hope it will help you

Google Maps - Make route line follow streets when map zoomed in

I'm getting the same issue as described in following SO questions:
(The route lines is not following the streets when I zoom in)
MapKit - Make route line follow streets when map zoomed in
and
Route drawing on Google Maps for iOS not following the street lines
But seems there are no any answer which solved mentioned issue.
I'm adding to points to the my GMSMapView map by following function:
-(void) addPointToMap:(CLLocationCoordinate2D) coordinate
{
CLLocationCoordinate2D position = CLLocationCoordinate2DMake(
coordinate.latitude,
coordinate.longitude);
GMSMarker *marker = [GMSMarker markerWithPosition:position];
marker.map = mapView_;
[waypoints_ addObject:marker];
NSString *positionString = [[NSString alloc] initWithFormat:#"%f,%f",
coordinate.latitude,coordinate.longitude];
[waypointStrings_ addObject:positionString];
if([waypoints_ count]>1){
NSString *sensor = #"false";
NSArray *parameters = [NSArray arrayWithObjects:sensor, waypointStrings_,
nil];
NSArray *keys = [NSArray arrayWithObjects:#"sensor", #"waypoints", nil];
NSDictionary *query = [NSDictionary dictionaryWithObjects:parameters
forKeys:keys];
MDDirectionService *mds=[[MDDirectionService alloc] init];
SEL selector = #selector(addDirections:);
[mds setDirectionsQuery:query
withSelector:selector
withDelegate:self];
}
}
and here are setDirectionsQuery function:
static NSString *kMDDirectionsURL = #"http://maps.googleapis.com/maps/api/directions/json?";
- (void)setDirectionsQuery:(NSDictionary *)query withSelector:(SEL)selector
withDelegate:(id)delegate{
NSArray *waypoints = [query objectForKey:#"waypoints"];
NSString *origin = [waypoints objectAtIndex:0];
int waypointCount = [waypoints count];
int destinationPos = waypointCount -1;
NSString *destination = [waypoints objectAtIndex:destinationPos];
NSString *sensor = [query objectForKey:#"sensor"];
NSMutableString *url =
[NSMutableString stringWithFormat:#"%#&origin=%#&destination=%#&sensor=%#",
kMDDirectionsURL,origin,destination, sensor];
if(waypointCount>2) {
[url appendString:#"&waypoints=optimize:true"];
int wpCount = waypointCount-2;
for(int i=1;i<wpCount;i++){
[url appendString: #"|"];
[url appendString:[waypoints objectAtIndex:i]];
}
}
url = [url
stringByAddingPercentEscapesUsingEncoding: NSASCIIStringEncoding];
_directionsURL = [NSURL URLWithString:url];
[self retrieveDirections:selector withDelegate:delegate];
}
Note: I have followed this Google tutorial and modified it a little bit:
https://www.youtube.com/watch?v=AdV7bCWuDYg
Thanks in advance, any help will be appreciated!
Finally I have found solution, Thanks to the WWJD's last edit in his question!
Route drawing on Google Maps for iOS not following the street lines
From the answer:
What I basically did before was that I was getting and working only with the information I'm receiving in the routes while if you check the JSON file you're receiving from Google Directions API, you'll see that you receive much more information in the and the . This is the information we need to produce the proper results and the right polyline.

Resources