Chad Schultz
Chad Schultz

Reputation: 7860

Programmatically getting directions using Apple Maps

I'm a bit confused by the documentation. After some research and experimentation, this is what I have.

if ([self canUseMKMapItem]) {
            [self iosTheMap];
        } else {
            [self googleTheMap];
        }

Using this to detect whether we can use the IOS6 mapping features:

- (BOOL) canUseMKMapItem {
    Class itemClass = [MKMapItem class];
    return (itemClass && [itemClass respondsToSelector:@selector(openMapsWithItems:launchOptions:)]);
}

This for IOS5, using Google Maps. It automatically takes us to a screen with a list of directions from the current address (if the user allows) to the destination.

- (void)googleTheMap
{
    NSNumber *userLat = [[NSNumber alloc]initWithDouble:mapView.userLocation.coordinate.latitude];
    NSNumber *userLong = [[NSNumber alloc]initWithDouble:mapView.userLocation.coordinate.longitude];

    NSMutableString *queryString = [NSMutableString stringWithFormat:@"http://maps.google.com/?saddr=%@,%@&daddr=",userLat,userLong];
    NSString *address = [partnerObject valueForKey:ATTRIBUTE_ADDRESS];
    [queryString appendString:address];
    NSString *escaped = [queryString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:escaped]];
}

Here's the tricky part--this is what I'm trying to do to use Apple Maps

- (void)iosTheMap {
    NSNumber * latitude = [partnerObject valueForKey:ATTRIBUTE_LATITUDE];
    NSNumber * longitude = [partnerObject valueForKey:ATTRIBUTE_LONGITUDE];
    CLLocationCoordinate2D coordinate;
    coordinate.latitude = latitude.doubleValue;
    coordinate.longitude = longitude.doubleValue;
    NSMutableDictionary *addressDictionary = [[NSMutableDictionary alloc] init];
    [addressDictionary setValue:[partnerObject valueForKey:ATTRIBUTE_ADDRESS] forKey:kABPersonAddressStreetKey];
    MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:coordinate addressDictionary:addressDictionary];
    MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
    [mapItem openInMapsWithLaunchOptions:nil];
}

This "works," sort of. It takes the user to a map screen with a pin showing the address. The user can tap that and get directions. However, I have a few reservations about this approach:

  1. I have a compiler warning where I set kABPersonAddressStreetKey: "Incompatible pointer types sending 'const CFStringRef' (aka 'const struct __CFString *const') to parameter of type 'NSString *'"
  2. The string value I am using is the full address. I use that value for the street address, although the address values are meant to be more atomic--street, city, state. It seems to work, but I'm concerned this isn't the right way to do it.
  3. It would be nice if Apple Maps showed the name of the business/destination, not just the address.
  4. It would be great to have Apple Maps automatically show the directions, instead of a map with the destination point, saving the user a few taps.

Any suggestions for how I can improve my approach? Although it seems to work, I suspect that it is not the right way.

Upvotes: 2

Views: 4359

Answers (1)

Mongo
Mongo

Reputation: 2674

You are pretty close. You need to specify the Launch Options dictionary for the openInMapsWithLaunchOptions function using the MKLaunchOptionsDirectionsModeDriving, MKLaunchOptionsDirectionsModeKey value and key.

    Class itemClass = [MKMapItem class];
    if (itemClass && [itemClass respondsToSelector:@selector(openMapsWithItems:launchOptions:)]) {
        // Use iOS 6 maps
        CLLocationCoordinate2D coordinate = [((LocationAnnotation*)[map.annotations objectAtIndex:0]) coordinate];
        MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:coordinate addressDictionary:nil];
        MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
        [mapItem openInMapsWithLaunchOptions:[NSDictionary dictionaryWithObjectsAndKeys:MKLaunchOptionsDirectionsModeDriving, MKLaunchOptionsDirectionsModeKey, nil]];
    } else {
        //Fall back on google
        ...
    }

Upvotes: 8

Related Questions