For learning purposes I'm trying to develop an app which will show directions to a specific point on a MKMapView.
However, the DirectionsResponse gives me the following error everytime, no matter the address:
2013-12-28 17:52:23.100 routingApp[378:70b] ERROR
2013-12-28 17:52:23.102 routingApp[378:70b] Directions Not Available
I only have a View Controller with a map view and the following code:
routingAppViewController.h
@interface routingAppViewController : UIViewController
@property (strong, nonatomic) IBOutlet MKMapView *mapView;
@property (strong, nonatomic) MKPlacemark *destination;
@end
routingAppViewController.m
#import "routingAppViewController.h"
@interface routingAppViewController ()
@end
@implementation routingAppViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *Location = @"385 Mid Avenue Weston";
_mapView.showsUserLocation = YES;
[self getDirections:Location];
}
-(void)getDirections:(NSString *)address{
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:address
completionHandler:^(NSArray* placemarks, NSError* error){
// Check for returned placemarks
if (placemarks && placemarks.count > 0) {
CLPlacemark *topResult = [placemarks objectAtIndex:0];
// Create a MLPlacemark and add it to the map view
MKPlacemark *placemark = [[MKPlacemark alloc] initWithPlacemark:topResult];
[self.mapView addAnnotation:placemark];
_destination = placemark;
}
}];
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:_destination];
MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
request.source = [MKMapItem mapItemForCurrentLocation];
request.destination = mapItem;
request.requestsAlternateRoutes = NO;
MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
[directions calculateDirectionsWithCompletionHandler:
^(MKDirectionsResponse *response, NSError *error) {
if (error) {
NSLog(@"ERROR");
NSLog(@"%@",[error localizedDescription]);
} else {
[self showRoute:response];
}
}];
}
-(void)showRoute:(MKDirectionsResponse *)response
{
for (MKRoute *route in response.routes)
{
[_mapView
addOverlay:route.polyline level:MKOverlayLevelAboveRoads];
for (MKRouteStep *step in route.steps)
{
NSLog(@"%@", step.instructions);
}
}
}
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id < MKOverlay >)overlay
{
MKPolylineRenderer *renderer =
[[MKPolylineRenderer alloc] initWithOverlay:overlay];
renderer.strokeColor = [UIColor blueColor];
renderer.lineWidth = 5.0;
return renderer;
}
The error is given in the getDirections
method.
I googled it and mostly the error means that the direction service is not available for this country. However i'm using an USA address, so I can't see why it's not working.
The annotation is added correctly and my location is set to "Apple".
Help much appreciated!
The completionHandler
block called by geocodeAddressString
is asynchronous.
This means that the code that tries to get the directions from the current location to _destination
runs immediately after the geocodeAddressString
line and executes before _destination
is set.
So when mapItem
is created, it is using _destination
still set to nil
(the geocoder block hasn't finished and set _destination
yet).
Trying to get directions from the current location to nil
results in the get directions error.
The simplest fix is to move the code that gets the directions request inside the completionHandler
block of geocodeAddressString
(right after _destination
is actually set):
[self.mapView addAnnotation:placemark];
_destination = placemark;
//move the code that gets the directions here,
//inside this block...
MKMapItem *mapItem = [[MKMapItem alloc] init...
...
[directions calculateDirections...
}