0

I am trying to integrate Apple Maps in my iPhone app to show route between two locations. But it wont show any route & will simple print lots of messages in console.

I am located in Mumbai, India. When I tried to use official Maps app on iPhone to search route it gave me warning that, 'No routes found'!

When in simulator I use two predefined location in U.S. it plotted the route, along with alternative routes correctly. So I came to conclusion that, Apple Map service is very limited outside U.S. (especially in India).

I want to use native services as much possible, but now that seems difficult. Do anyone have idea about this issue & it this is the case then what are the other options?

Following are code sample from both cases:

India (No result):

let request: MKDirectionsRequest = MKDirectionsRequest()
request.source = MKMapItem(placemark: MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: 19.02, longitude: 72.85), addressDictionary: nil))
request.destination = MKMapItem(placemark: MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: 19.12, longitude: 73.85), addressDictionary: nil))
request.transportType = MKDirectionsTransportType.automobile;
request.requestsAlternateRoutes = true

let directions = MKDirections(request: request)

directions.calculate { [unowned self] response, error in
    guard let unwrappedResponse = response else { return }
    for route in unwrappedResponse.routes {
        self.mapView.add(route.polyline)
        self.mapView.setVisibleMapRect(route.polyline.boundingMapRect, animated: true)
    }
}

U.S. (Gave proper routes)

let request: MKDirectionsRequest = MKDirectionsRequest()
request.source = MKMapItem(placemark: MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: 40.71, longitude: -74.00), addressDictionary: nil))
request.destination = MKMapItem(placemark: MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: 37.78, longitude: -122.41), addressDictionary: nil))
request.transportType = MKDirectionsTransportType.automobile;
request.requestsAlternateRoutes = true

let directions = MKDirections(request: request)

directions.calculate { [unowned self] response, error in
    guard let unwrappedResponse = response else { return }
    for route in unwrappedResponse.routes {
        self.mapView.add(route.polyline)
        self.mapView.setVisibleMapRect(route.polyline.boundingMapRect, animated: true)
    }
}

While researching I found this link: http://www.apple.com/in/ios/feature-availability/

In Maps: Directions section India is not listed, so I don't think I'll be able to use this feature in my app :(

I am familiar with Google Maps, but are there any other option to overcome this problem with minimum shift from native services?

demonofthemist
  • 4,081
  • 4
  • 26
  • 45

1 Answers1

0

Here is what i did:

1.From the google map api: "http://maps.google.com/maps?output=dragdir&saddr=%@&daddr=%@" by passing the source and destination in response i have received the route points.

  1. Then i have encoded that points

  2. Using that point i have drawn polyline and added that polyline to the apple map

Refer this code in ObjectiveC:

// Route
#pragma mark --------------------- Custom Methods For Displaying Route ---------------------

-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t {

    NSString* saddr = [NSString stringWithFormat:@"%f,%f", f.latitude, f.longitude];
    NSString* daddr = [NSString stringWithFormat:@"%f,%f", t.latitude, t.longitude];

    NSString* apiUrlStr = [NSString stringWithFormat:@"http://maps.google.com/maps?output=dragdir&saddr=%@&daddr=%@", saddr, daddr];
    NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
    NSLog(@"api url: %@", apiUrl);
    NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl];
    NSString* encodedPoints = [apiResponse stringByMatching:@"points:\\\"([^\\\"]*)\\\"" capture:1L];

    return [self decodePolyLine:[encodedPoints mutableCopy]];
}


-(NSMutableArray *)decodePolyLine: (NSMutableString *)encoded {
    [encoded replaceOccurrencesOfString:@"\\\\" withString:@"\\"
                                options:NSLiteralSearch
                                  range:NSMakeRange(0, [encoded length])];
    NSInteger len = [encoded length];
    NSInteger index = 0;
    NSMutableArray *array = [[NSMutableArray alloc] init];
    NSInteger lat=0;
    NSInteger lng=0;
    while (index < len) {
        NSInteger b;
        NSInteger shift = 0;
        NSInteger result = 0;
        do {
            b = [encoded characterAtIndex:index++] - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
        lat += dlat;
        shift = 0;
        result = 0;
        do {
            b = [encoded characterAtIndex:index++] - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
        lng += dlng;
        NSNumber *latitude = [[NSNumber alloc] initWithFloat:lat * 1e-5];
        NSNumber *longitude = [[NSNumber alloc] initWithFloat:lng * 1e-5];
        printf("[%f,", [latitude doubleValue]);
        printf("%f]", [longitude doubleValue]);
        CLLocation *loc = [[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]];
        [array addObject:loc];
    }

    return array;
}

-(void) updateRouteView {
    CGContextRef context = CGBitmapContextCreate(nil,
                                                  _imageViewForRoute.frame.size.width,
                                                  _imageViewForRoute.frame.size.height,
                                                  8,
                                                  4 * _imageViewForRoute.frame.size.width,
                                                  CGColorSpaceCreateDeviceRGB(),
                                                  kCGImageAlphaPremultipliedLast);

    CGContextSetStrokeColorWithColor(context, _colorForRouteLine.CGColor);
    CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
    CGContextSetLineWidth(context, 1.0);

    for(int i = 0; i < _arraForRoutePoints.count; i++) {
        CLLocation* location = [_arraForRoutePoints objectAtIndex:i];
        CGPoint point = [_mapViewForLocation convertCoordinate:location.coordinate toPointToView:_imageViewForRoute];

        if(i == 0) {
            CGContextMoveToPoint(context, point.x, _imageViewForRoute.frame.size.height - point.y);
        } else {
            CGContextAddLineToPoint(context, point.x, _imageViewForRoute.frame.size.height - point.y);
        }
    }

    //CGContextRef context = UIGraphicsGetCurrentContext();
    CGFloat lengths[2];
    lengths[0] = 0;
    lengths[1] = 4 * 2;
    CGContextSetLineCap(context, kCGLineCapRound);
    CGContextSetLineWidth(context, 4);
    CGContextSetLineDash(context, 0.0f, lengths, 2);

    CGContextStrokePath(context);


    CGImageRef image = CGBitmapContextCreateImage(context);
    UIImage* img = [UIImage imageWithCGImage:image];

    _imageViewForRoute.image = img;
    CGContextRelease(context);

}

-(void) centerMap {
    MKCoordinateRegion region;

    CLLocationDegrees maxLat = -90;
    CLLocationDegrees maxLon = -180;
    CLLocationDegrees minLat = 90;
    CLLocationDegrees minLon = 180;
    for(int idx = 0; idx < _arraForRoutePoints.count; idx++)
    {
        CLLocation* currentLocation = [_arraForRoutePoints objectAtIndex:idx];
        if(currentLocation.coordinate.latitude > maxLat)
            maxLat = currentLocation.coordinate.latitude;
        if(currentLocation.coordinate.latitude < minLat)
            minLat = currentLocation.coordinate.latitude;
        if(currentLocation.coordinate.longitude > maxLon)
            maxLon = currentLocation.coordinate.longitude;
        if(currentLocation.coordinate.longitude < minLon)
            minLon = currentLocation.coordinate.longitude;
    }
    region.center.latitude     = (maxLat + minLat) / 2;
    region.center.longitude    = (maxLon + minLon) / 2;
    region.span.latitudeDelta  = maxLat - minLat;
    region.span.longitudeDelta = maxLon - minLon;

    MKCoordinateSpan coordinateSpan = MKCoordinateSpanMake(0.02, 0.02);
     MKCoordinateRegion coordinateRegion = MKCoordinateRegionMake(region.center, coordinateSpan);

    [_mapViewForLocation setRegion:coordinateRegion animated:TRUE];
    [_mapViewForLocation regionThatFits:coordinateRegion];

}

// Route
- (IBAction)fnForShowRouteButtonClicked:(id)sender {

    _arraForRoutePoints = [self calculateRoutesFrom:_sourceLocation to:_destinationLocation];

    [self updateRouteView];
    [self centerMap];


}

Refer Links You will need for Swift:

Community
  • 1
  • 1
Suhas Arvind Patil
  • 1,732
  • 1
  • 19
  • 31