route google iphone objective-c json google-polyline google-direction

iphone - ios google map sdk draw route



¿Cómo decodificar el campo de polilíneas de la API de Google Directions en puntos largos en el objetivo-C para iPhone? (12)

Quiero dibujar rutas en un mapa que corresponda a las direcciones JSON que recibo a través de la API de Google Directions: http://code.google.com/apis/maps/documentation/directions/

He descubierto cómo extraer la latitud y la longitud del campo de pasos, sin embargo esto no sigue muy bien los caminos con curvas. Creo que lo que necesito es descifrar la información de la polilínea, encontré instrucciones de Google sobre cómo codificar polilíneas: http://code.google.com/apis/maps/documentation/utilities/polylinealgorithm.html

Encontré un código aquí para Android y también Javascript para decodificar las polilíneas, por ejemplo:

Vista de mapa dibujar direcciones usando la API de indicaciones de Google - descifrar polilíneas

Android consigue y analiza Google Directions

Pero no puedo encontrar el mismo código de iPhone para Objective-C, ¿alguien puede ayudarme con esto? Estoy seguro de que puedo hacerlo yo mismo si tengo que hacerlo, pero seguro que me ahorraría algo de tiempo si ya está disponible en algún lugar ...

EDITAR: la clave aquí es poder decodificar la codificación base64 en una base de carácter por carácter. Para ser más específico, obtengo algo como esto en JSON de Google que está codificado usando la codificación base64 entre otras cosas:

... "overview_polyline" : { "points" : "ydelDz~vpN_@NO@QEKWIYIIO?YCS@WFGBEBICCAE?G@y@RKBEBEBAD?HTpB@LALALCNEJEFSP_@LyDv@aB//GBMB" }, ...

Nota: Debo mencionar que esta pregunta se refiere a la API v1 de Google Maps, es mucho más fácil hacerlo en v2 utilizando GMSPolyLine polyLineWithPath, ya que muchas respuestas a continuación le dirán (gracias a @cdescours).


Implementación Python

Esto no está en Objective-C, pero este hilo es donde Google te deja si estás buscando decodificar cadenas de polilínea de Google Maps. En caso de que alguien más lo necesite (como lo hice yo), aquí hay una implementación de Python para decodificar cadenas de polilínea. Esto es portado desde la versión de JavaScript de Mapbox; Más información encontrada en mi página de repo.

def decode_polyline(polyline_str): index, lat, lng = 0, 0, 0 coordinates = [] changes = {''latitude'': 0, ''longitude'': 0} # Coordinates have variable length when encoded, so just keep # track of whether we''ve hit the end of the string. In each # while loop iteration, a single coordinate is decoded. while index < len(polyline_str): # Gather lat/lon changes, store them in a dictionary to apply them later for unit in [''latitude'', ''longitude'']: shift, result = 0, 0 while True: byte = ord(polyline_str[index]) - 63 index+=1 result |= (byte & 0x1f) << shift shift += 5 if not byte >= 0x20: break if (result & 1): changes[unit] = ~(result >> 1) else: changes[unit] = (result >> 1) lat += changes[''latitude''] lng += changes[''longitude''] coordinates.append((lat / 100000.0, lng / 100000.0)) return coordinates


Así es como lo hago en mi aplicación de direcciones. keyPlace es su objeto de destino

- (void)getDirections { CLLocation *newLocation;// = currentUserLocation; MKPointAnnotation *annotation = [[[MKPointAnnotation alloc] init] autorelease]; annotation.coordinate = CLLocationCoordinate2DMake(newLocation.coordinate.latitude, newLocation.coordinate.longitude); annotation.title = @"You"; [mapView addAnnotation:annotation]; CLLocationCoordinate2D endCoordinate; NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"https://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%f,%f&sensor=false&mode=walking", newLocation.coordinate.latitude, newLocation.coordinate.longitude, keyPlace.lat, keyPlace.lon]]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request startSynchronous]; if ([[request.responseString.JSONValue valueForKey:@"status"] isEqualToString:@"ZERO_RESULTS"]) { [[[[UIAlertView alloc] initWithTitle:@"Error" message:@"Could not route path from your current location" delegate:nil cancelButtonTitle:@"Close" otherButtonTitles:nil, nil] autorelease] show]; self.navigationController.navigationBar.userInteractionEnabled = YES; return; } int points_count = 0; if ([[request.responseString.JSONValue objectForKey:@"routes"] count]) points_count = [[[[[[request.responseString.JSONValue objectForKey:@"routes"] objectAtIndex:0] objectForKey:@"legs"] objectAtIndex:0] objectForKey:@"steps"] count]; if (!points_count) { [[[[UIAlertView alloc] initWithTitle:@"Error" message:@"Could not route path from your current location" delegate:nil cancelButtonTitle:@"Close" otherButtonTitles:nil, nil] autorelease] show]; self.navigationController.navigationBar.userInteractionEnabled = YES; return; } CLLocationCoordinate2D points[points_count * 2]; int j = 0; NSArray *steps = nil; if (points_count && [[[[request.responseString.JSONValue objectForKey:@"routes"] objectAtIndex:0] objectForKey:@"legs"] count]) steps = [[[[[request.responseString.JSONValue objectForKey:@"routes"] objectAtIndex:0] objectForKey:@"legs"] objectAtIndex:0] objectForKey:@"steps"]; for (int i = 0; i < points_count; i++) { double st_lat = [[[[steps objectAtIndex:i] objectForKey:@"start_location"] valueForKey:@"lat"] doubleValue]; double st_lon = [[[[steps objectAtIndex:i] objectForKey:@"start_location"] valueForKey:@"lng"] doubleValue]; //NSLog(@"lat lon: %f %f", st_lat, st_lon); if (st_lat > 0.0f && st_lon > 0.0f) { points[j] = CLLocationCoordinate2DMake(st_lat, st_lon); j++; } double end_lat = [[[[steps objectAtIndex:i] objectForKey:@"end_location"] valueForKey:@"lat"] doubleValue]; double end_lon = [[[[steps objectAtIndex:i] objectForKey:@"end_location"] valueForKey:@"lng"] doubleValue]; if (end_lat > 0.0f && end_lon > 0.0f) { points[j] = CLLocationCoordinate2DMake(end_lat, end_lon); endCoordinate = CLLocationCoordinate2DMake(end_lat, end_lon); j++; } } MKPolyline *polyline = [MKPolyline polylineWithCoordinates:points count:points_count * 2]; [mapView addOverlay:polyline]; } #pragma mark - MapKit - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation { MKPinAnnotationView *annView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"currentloc"] autorelease]; annView.canShowCallout = YES; annView.animatesDrop = YES; return annView; } - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay { MKPolylineView *overlayView = [[[MKPolylineView alloc] initWithOverlay:overlay] autorelease]; overlayView.lineWidth = 5; overlayView.strokeColor = [UIColor purpleColor]; overlayView.fillColor = [[UIColor purpleColor] colorWithAlphaComponent:0.5f]; return overlayView; }


En caso de que alguien necesite el código de decodificación en VBA, aquí hay un puerto (en funcionamiento):

Function decodeGeopoints(encoded) decodeGeopoints = "" '' This code is a port to VBA from code published here: '' http://blog.synyx.de/2010/06/routing-driving-directions-on-android-part-1-get-the-route/ ''//decoding ''List poly = new ArrayList(); ''// replace two backslashes by one (some error from the transmission) ''encoded = encoded.replace("//", "/"); encoded = Replace(encoded, "//", "/") ''int index = 0, len = encoded.length(); Dim index As Long index = 0 Dim leng As Long leng = Len(encoded) ''int lat = 0, lng = 0; Dim lat As Long lat = 0 Dim lng As Long lng = 0 ''while (index < len) { While (index < leng) ''int b, shift = 0, result = 0; Dim b, shift, result As Long b = 0 shift = 0 result = 0 ''do { Do ''b = encoded.charAt(index++) - 63; index = index + 1 b = Asc(Mid(encoded, index, 1)) - 63 ''result |= (b & 0x1f) << shift; result = result Or ((b And 31) * (2 ^ shift)) ''shift += 5; shift = shift + 5 ''} while (b >= 0x20); Loop While (b >= 32) ''int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); Dim dlat As Long If (result And 1) <> 0 Then dlat = Not Int(result / 2) Else dlat = Int(result / 2) End If ''lat += dlat; lat = lat + dlat ''shift = 0; shift = 0 ''result = 0; result = 0 ''do { Do ''b = encoded.charAt(index++) - 63; index = index + 1 b = Asc(Mid(encoded, index, 1)) - 63 ''result |= (b & 0x1f) << shift; result = result Or ((b And 31) * (2 ^ shift)) ''shift += 5; shift = shift + 5 ''} while (b >= 0x20); Loop While (b >= 32) ''int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); Dim dlng As Long If (result And 1) <> 0 Then dlng = Not Int(result / 2) Else dlng = Int(result / 2) End If ''lng += dlng; lng = lng + dlng ''GeoPoint p = new GeoPoint((int) (((double) lat / 1E5) * 1E6), (int) (((double) lng / 1E5) * 1E6)); Dim myLat, myLng As Double myLat = (lat / 100000) ''myLat = myLat * 1000000 myLng = (lng / 100000) ''myLng = myLng * 1000000 ''poly.add(p); decodeGeopoints = decodeGeopoints & Comma2Dot(myLng) & "," & Comma2Dot(myLat) & ",0 " ''} Wend End Function


Espero que no esté en contra de las reglas vincular a mi propia publicación de blog si es relevante para la pregunta, pero he resuelto este problema en el pasado. Respuesta independiente de la publicación vinculada:

@implementation MKPolyline (MKPolyline_EncodedString) + (MKPolyline *)polylineWithEncodedString:(NSString *)encodedString { const char *bytes = [encodedString UTF8String]; NSUInteger length = [encodedString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; NSUInteger idx = 0; NSUInteger count = length / 4; CLLocationCoordinate2D *coords = calloc(count, sizeof(CLLocationCoordinate2D)); NSUInteger coordIdx = 0; float latitude = 0; float longitude = 0; while (idx < length) { char byte = 0; int res = 0; char shift = 0; do { byte = bytes[idx++] - 63; res |= (byte & 0x1F) << shift; shift += 5; } while (byte >= 0x20); float deltaLat = ((res & 1) ? ~(res >> 1) : (res >> 1)); latitude += deltaLat; shift = 0; res = 0; do { byte = bytes[idx++] - 0x3F; res |= (byte & 0x1F) << shift; shift += 5; } while (byte >= 0x20); float deltaLon = ((res & 1) ? ~(res >> 1) : (res >> 1)); longitude += deltaLon; float finalLat = latitude * 1E-5; float finalLon = longitude * 1E-5; CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(finalLat, finalLon); coords[coordIdx++] = coord; if (coordIdx == count) { NSUInteger newCount = count + 10; coords = realloc(coords, newCount * sizeof(CLLocationCoordinate2D)); count = newCount; } } MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:coordIdx]; free(coords); return polyline; } @end


Esta es mi propia revisión de la respuesta de Sedate Alien. Es la misma implementación guardada para eliminar el código duplicado y usar NSMutableData en lugar de asignar cosas manualmente.

@implementation MKPolyline (EncodedString) + (float)decodeBytes:(const char *)bytes atPos:(NSUInteger *)idx toValue:(float *)value { char byte = 0; int res = 0; char shift = 0; do { byte = bytes[(*idx)++] - 0x3F; res |= (byte & 0x1F) << shift; shift += 5; } while (byte >= 0x20); (*value) += ((res & 1) ? ~(res >> 1) : (res >> 1)); return (*value) * 1E-5; } + (MKPolyline *)polylineWithEncodedString:(NSString *)encodedString { const char *bytes = [encodedString UTF8String]; NSUInteger length = [encodedString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; NSUInteger idx = 0; NSMutableData *data = [NSMutableData data]; float lat = 0; float lon = 0; CLLocationCoordinate2D coords = CLLocationCoordinate2DMake(0, 0); while (idx < length) { coords.latitude = [self decodeBytes:bytes atPos:&idx toValue:&lat]; coords.longitude = [self decodeBytes:bytes atPos:&idx toValue:&lon]; [data appendBytes:&coords length:sizeof(CLLocationCoordinate2D)]; } return [MKPolyline polylineWithCoordinates:(CLLocationCoordinate2D *)data.bytes count:data.length / sizeof(CLLocationCoordinate2D)]; } @end


La mejor y más ligera respuesta debería ser utilizar el método provisto por Google en el marco:

[GMSPolyline polylineWithPath:[GMSPath pathFromEncodedPath:encodedPath]]


Las otras respuestas aquí parecen ser sobre el uso de Apple Maps, para el uso de Google Maps, encontré que tuve que hacer algunas modificaciones en la gran categoría de @ SedateAlien.

Categoría modificada

+ (GMSPolyline *)polylineWithEncodedString:(NSString *)encodedString { const char *bytes = [encodedString UTF8String]; NSUInteger length = [encodedString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; NSUInteger idx = 0; NSUInteger count = length / 4; CLLocationCoordinate2D *coords = calloc(count, sizeof(CLLocationCoordinate2D)); NSUInteger coordIdx = 0; float latitude = 0; float longitude = 0; while (idx < length) { char byte = 0; int res = 0; char shift = 0; do { byte = bytes[idx++] - 63; res |= (byte & 0x1F) << shift; shift += 5; } while (byte >= 0x20); float deltaLat = ((res & 1) ? ~(res >> 1) : (res >> 1)); latitude += deltaLat; shift = 0; res = 0; do { byte = bytes[idx++] - 0x3F; res |= (byte & 0x1F) << shift; shift += 5; } while (byte >= 0x20); float deltaLon = ((res & 1) ? ~(res >> 1) : (res >> 1)); longitude += deltaLon; float finalLat = latitude * 1E-5; float finalLon = longitude * 1E-5; CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(finalLat, finalLon); coords[coordIdx++] = coord; if (coordIdx == count) { NSUInteger newCount = count + 10; coords = realloc(coords, newCount * sizeof(CLLocationCoordinate2D)); count = newCount; } } GMSMutablePath *path = [[GMSMutablePath alloc] init]; int i; for (i = 0; i < coordIdx; i++) { [path addCoordinate:coords[i]]; } GMSPolyline *polyline = [GMSPolyline polylineWithPath:path]; free(coords); return polyline; }

USO

// Here I make the call to the Google Maps API to get the routes between two points... .... // Get the encoded array of points. NSString *points = routes[@"routes"][0][@"overview_polyline"][@"points"]; // Use the modified category to get a polyline from the points. GMSPolyline *polyline = [GMSPolyline polylineWithEncodedString:points]; // Add the polyline to the map. polyline.strokeColor = [UIColor redColor]; polyline.strokeWidth = 10.f; polyline.map = theMapView; }


Para los mapas de Google ya tiene un método directo, polylineWithPath , así que prefiero este fragmento.

-(void)drawPathFrom:(CLLocation*)source toDestination:(CLLocation*)destination{ NSString *baseUrl = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%f,%f&sensor=true", source.coordinate.latitude, source.coordinate.longitude, destination.coordinate.latitude, destination.coordinate.longitude]; NSURL *url = [NSURL URLWithString:[baseUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; NSLog(@"Url: %@", url); NSURLRequest *request = [NSURLRequest requestWithURL:url]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { if(!connectionError){ NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; NSArray *routes = [result objectForKey:@"routes"]; NSDictionary *firstRoute = [routes objectAtIndex:0]; NSString *encodedPath = [firstRoute[@"overview_polyline"] objectForKey:@"points"]; GMSPolyline *polyPath = [GMSPolyline polylineWithPath:[GMSPath pathFromEncodedPath:encodedPath]]; polyPath.strokeColor = [UIColor redColor]; polyPath.strokeWidth = 3.5f; polyPath.map = _mapView; } }]; }


Si alguien más está tratando de hacer esto rápidamente, aquí está la respuesta de @ RootCode adaptada a swift (2.3):

let path = GMSMutablePath() let steps = directionsToShowOnMap.steps for (idx, step) in steps.enumerate() { path.addCoordinate(coordinateFromJson(step["start_location"])) if let polylinePoints = step["polyline"].string, subpath = GMSPath(fromEncodedPath: polylinePoints) { for c in 0 ..< subpath.count() { path.addCoordinate(subpath.coordinateAtIndex(c)) } } if idx == steps.count - 1 { path.addCoordinate(coordinateFromJson(step["end_location"])) } } let polyline = GMSPolyline(path: path) polyline.strokeColor = UIColor.blueColor() polyline.strokeWidth = 3 polyline.map = mapView

y entonces:

private func coordinateFromJson(location: JSON) -> CLLocationCoordinate2D { return CLLocationCoordinate2DMake(location["lat"].double!, location["lng"].double!) }


Si está trabajando con Google Map en iOS y desea dibujar la ruta, incluidas las polilíneas, el mismo Google proporciona una manera más fácil de obtener el GMSPath desde la polilínea como,

GMSPath *pathFromPolyline = [GMSPath pathFromEncodedPath:polyLinePoints];

Aquí está el código completo:

+ (void)callGoogleServiceToGetRouteDataFromSource:(CLLocation *)sourceLocation toDestination:(CLLocation *)destinationLocation onMap:(GMSMapView *)mapView_{ NSString *baseUrl = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%f,%f&sensor=false", sourceLocation.coordinate.latitude, sourceLocation.coordinate.longitude, destinationLocation.coordinate.latitude, destinationLocation.coordinate.longitude]; NSURL *url = [NSURL URLWithString:[baseUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; NSLog(@"Url: %@", url); NSURLRequest *request = [NSURLRequest requestWithURL:url]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { GMSMutablePath *path = [GMSMutablePath path]; NSError *error = nil; NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; NSArray *routes = [result objectForKey:@"routes"]; NSDictionary *firstRoute = [routes objectAtIndex:0]; NSDictionary *leg = [[firstRoute objectForKey:@"legs"] objectAtIndex:0]; NSArray *steps = [leg objectForKey:@"steps"]; int stepIndex = 0; CLLocationCoordinate2D stepCoordinates[1 + [steps count] + 1]; for (NSDictionary *step in steps) { NSDictionary *start_location = [step objectForKey:@"start_location"]; stepCoordinates[++stepIndex] = [self coordinateWithLocation:start_location]; [path addCoordinate:[self coordinateWithLocation:start_location]]; NSString *polyLinePoints = [[step objectForKey:@"polyline"] objectForKey:@"points"]; GMSPath *polyLinePath = [GMSPath pathFromEncodedPath:polyLinePoints]; for (int p=0; p<polyLinePath.count; p++) { [path addCoordinate:[polyLinePath coordinateAtIndex:p]]; } if ([steps count] == stepIndex){ NSDictionary *end_location = [step objectForKey:@"end_location"]; stepCoordinates[++stepIndex] = [self coordinateWithLocation:end_location]; [path addCoordinate:[self coordinateWithLocation:end_location]]; } } GMSPolyline *polyline = nil; polyline = [GMSPolyline polylineWithPath:path]; polyline.strokeColor = [UIColor grayColor]; polyline.strokeWidth = 3.f; polyline.map = mapView_; }]; } + (CLLocationCoordinate2D)coordinateWithLocation:(NSDictionary*)location { double latitude = [[location objectForKey:@"lat"] doubleValue]; double longitude = [[location objectForKey:@"lng"] doubleValue]; return CLLocationCoordinate2DMake(latitude, longitude); }


Swift 3.0

let polyline = GMSPolyline(path: GMSPath.init(fromEncodedPath: encodedPolyline))


- (MKPolyline *)polylineWithEncodedString:(NSString *)encodedString { const char *bytes = [encodedString UTF8String]; NSUInteger length = [encodedString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; NSUInteger idx = 0; NSUInteger count = length / 4; CLLocationCoordinate2D *coords = calloc(count, sizeof(CLLocationCoordinate2D)); NSUInteger coordIdx = 0; float latitude = 0; float longitude = 0; while (idx < length) { char byte = 0; int res = 0; char shift = 0; do { byte = bytes[idx++] - 63; res |= (byte & 0x1F) << shift; shift += 5; } while (byte >= 0x20); float deltaLat = ((res & 1) ? ~(res >> 1) : (res >> 1)); latitude += deltaLat; shift = 0; res = 0; do { byte = bytes[idx++] - 0x3F; res |= (byte & 0x1F) << shift; shift += 5; } while (byte >= 0x20); float deltaLon = ((res & 1) ? ~(res >> 1) : (res >> 1)); longitude += deltaLon; float finalLat = latitude * 1E-5; float finalLon = longitude * 1E-5; CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(finalLat, finalLon); coords[coordIdx++] = coord; if (coordIdx == count) { NSUInteger newCount = count + 10; coords = realloc(coords, newCount * sizeof(CLLocationCoordinate2D)); count = newCount; } } MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:coordIdx]; free(coords); return polyline; } - (MKPolygonRenderer *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay { // MKPolygonRenderer *polylineView = [[MKPolygonRenderer alloc] initWithOverlay:overlay]; MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay]; polylineView.strokeColor = [UIColor redColor]; polylineView.lineWidth = 4.0; [self zoomToPolyLine:mapview polyline:overlay animated:YES]; return polylineView; } -(void)zoomToPolyLine: (MKMapView*)map polyline: (MKPolyline*)polyline animated: (BOOL)animated { [map setVisibleMapRect:[polyline boundingMapRect] edgePadding:UIEdgeInsetsMake(25.0, 25.0, 25.0, 25.0) animated:animated]; } - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { // NSLog(@"didUpdateToLocation: %@", newLocation); CLLocation *currentLocation = newLocation; if (currentLocation != nil) { currlong = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude]; currlt = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude]; } NSString *origin = [NSString stringWithFormat:@"%@%@%@",currlt,@",",currlong]; //I have just mention static location NSString *drivein = @"23.0472963,72.52757040000006"; NSString *apikey = [NSString stringWithFormat:@"https://maps.googleapis.com/maps/api/directions/json?origin=%@&destination=%@",origin,drivein]; NSURL *url = [NSURL URLWithString:apikey]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; NSURLResponse *response; NSError *error; NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]; if(!error) { NSData *data = [responseString dataUsingEncoding:NSUTF8StringEncoding]; NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; NSArray *routesArray = [jsonResponse objectForKey:@"routes"]; NSLog(@"route array %@",routesArray); if ([routesArray count] > 0) { NSDictionary *routeDict = [routesArray objectAtIndex:0]; NSDictionary *routeOverviewPolyline = [routeDict objectForKey:@"overview_polyline"]; NSString *points = [routeOverviewPolyline objectForKey:@"points"]; MKPolyline *line = [self polylineWithEncodedString:points]; [mapview addOverlay:line]; } } MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(currentLocation.coordinate, 500, 500); MKCoordinateRegion adjustedRegion = [mapview regionThatFits:viewRegion]; [mapview setRegion:adjustedRegion animated:YES]; mapview.showsUserLocation = YES; MKPointAnnotation *point = [[MKPointAnnotation alloc] init]; point.coordinate = currentLocation.coordinate; point.title = @"Your current Locations"; point.subtitle = @"You are here!"; [mapview addAnnotation:point]; [locationmanger stopUpdatingLocation]; }