0

I have created a map that has an MKPointAnnotation which is the single point on the map (besides the users location). I am trying to work out how to amend some existing code I have to get the Driving directions to this point.

This is the code that I use early in the application. At this earlier point in the application I have the following which gives me a CLPlaceMark.

[geocoder geocodeAddressString:location
             completionHandler:^(NSArray* placemarks, NSError* error){
                 if (placemarks && placemarks.count > 0) {
                     CLPlacemark *topResult = [placemarks objectAtIndex:0];

Collecting directions:

MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
                         [request setSource:[MKMapItem mapItemForCurrentLocation]];
                         MKPlacemark *mkDest = [[MKPlacemark alloc] initWithPlacemark:topResult];
                         [request setDestination:[[MKMapItem alloc] initWithPlacemark:mkDest]];
                         [request setTransportType:MKDirectionsTransportTypeWalking]; // This can be limited to automobile and walking directions.
                         [request setRequestsAlternateRoutes:NO]; 
                         MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
                         [directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
                             if (!error) {
                                 for (MKRoute *route in [response routes]) {
                                     [self.mapView addOverlay:[route polyline] level:MKOverlayLevelAboveRoads]; // Draws the route above roads, but below labels.
                                     // You can also get turn-by-turn steps, distance, advisory notices, ETA, etc by accessing various route properties.
                                 }
                             }
                         }];

Issue
The issue is that later on I seem to only be able to access the self.mapView.annotations. So I have access to the MKPointAnnotation, but I need access to a CLPlacemark for the setDestination on the MKDirectionsRequest.

So the question is how do I get a CLPacemark from a MKPointAnnotation, or is there a different approach to getting directions to a single point without that requirement? Thanks

StuartM
  • 6,743
  • 18
  • 84
  • 160
  • In geocodeAddressString, create the annotation as an `MKPlacemark` using [this answer](http://stackoverflow.com/a/8289073/467105) instead of the simple `MKPointAnnotation`. `MKPlacemark` also conforms to `MKAnnotation`. Then, to get directions, you can pass the annotation object (which will be an MKPlacemark) to MKMapItem's initWithPlacemark method. –  May 06 '14 at 17:04

3 Answers3

6

For the directions request, the MKMapItem needs an MKPlacemark (not a CLPlacemark).

You can create an MKPlacemark directly from coordinates using its initWithCoordinate:addressDictionary: method.

For example:

MKPlacemark *mkDest = [[MKPlacemark alloc] 
                          initWithCoordinate:pointAnnotation.coordinate 
                           addressDictionary:nil];

[request setDestination:[[MKMapItem alloc] initWithPlacemark:mkDest]];
0

MKPointAnnotation will give you the coordinate, which you can put into CLPlacemark's location.coordinate. I don't think there will be any other readily-available information within an MKPointAnnotation that would be usable in a CLPlacemark.

MKPointAnnotation *annotation = ...;
CLPlacemark *placemark = ...;

placemark.location.coordinate = annotation.coordinate;

Edit: Apologies, I didn't realize that CLPlacemarks are largely read-only. That being said, you can use a reverse-geocode on the coordinate of your MKPointAnnotation in order to get a CLPlacemark. This link has information on how to reverse-geocode to get your CLPlacemark from a CLLocation (populate the location.coordinate with your annotation.coordinate) to look up directions.

Stonz2
  • 6,306
  • 4
  • 44
  • 64
  • Yeah you can't create CLPlacemarks...they need to be gotten from CLGeocoder. The reason being is that they must be created using the MapKit projection system so the geocoding is actually fairly important. – smyrgl May 06 '14 at 17:04
  • Yeah, realized that after seeing @StuartM's comment and learned about the reverse geocoding. I almost prefer the answers where I'm wrong at first because then I learn something, too! – Stonz2 May 06 '14 at 17:06
0

You need to use the coordinate property of the MKPointAnnotation and then get the CLPlacemark via CLGeocoder using reverse geocode.

EDIT: Some sample code.

CLLocation *location = [[CLLocation alloc] initWithLatitude:annotation.coordinate.latitude longitude:annotation.coordinate.longitude];

CLGeocoder *geocoder = [CLGeocoder new];

[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemark, NSError *error){
    // Grab the placemark   
}];

Otherwise you need to cache the CLPlacemark which you can do on your annotation datasource if you like (remember MKAnnotation is a protocol, there is nothing saying you can't add a property to the backing model).

smyrgl
  • 864
  • 6
  • 12
  • For the directions request, the MKMapItem needs an MKPlacemark (not a CLPlacemark). You can create an MKPlacemark directly from coordinates using its initWithCoordinate:addressDictionary: method. So this reverse geocoding is unnecessary. –  May 06 '14 at 17:15
  • Ack, you are correct, I got CLPlacemark and MKPlacemark confused. It still needs to be reverse geocoded but it looks like MKPlacemark deals with it for you. – smyrgl May 06 '14 at 17:17
  • Actually, it's even better because MKPlacemark inherits from CLPlacemark so you can pass the annotation object of type MKPlacemark directly to MKMapItem's initWithPlacemark. –  May 06 '14 at 17:30
  • @Anna - Could you submit an answer as you proposed please and I can accept. I can use `[request setDestination:[[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:pointAnnotation.coordinate addressDictionary:nil]]];` as you suggest. Thanks – StuartM May 06 '14 at 22:05