How to use MapKit

Published on May 23, 2010

Apple seems to lack a MapKit programming guide. I have to look through the MapKit reference, search on the Internet, and read blog articles in order to do a few simple tasks with MapKit.

I thought it would be great if there is a MapKit programming guide, similar to the Push Notification Service programming guide provided by Apple.

But there isn’t. So I am here writing one for developers who are interested to use MapKit for that few simple tasks. This post contains 8 code snippets for 8 tasks.

 

1. Adding a map view

If you simply want to add a map to your view, simply create a MKMapView object and insert it. That’s our first big step!</p>

- (void)viewDidLoad {
  [super viewDidLoad];
  // Init our map view 
 mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
 [self.view insertSubview:mapView atIndex:];
}

 

2. Configuring the map

With a map, you could now configure various aspects by setting the mapView properties. Examples below:

 // Set the map type such as Standard, Satellite, Hybrid
 mapView.mapType = MKMapTypeStandard;
 
  // Config user interactions
 mapView.zoomEnabled = NO;
 mapView.scrollEnabled = YES;
 
  // Set the region and zoom level
  MKCoordinateRegion region;
  MKCoordinateSpan span;
  CLLocationCoordinate2D location;
  location.latitude = 1.302851; // Singapore!
 location.longitude = 103.85523;
 span.latitudeDelta = 0.02;
  span.longitudeDelta = 0.02;
 region.span = span;
 region.center = location;
 // Set to that region with an animated effect
 [mapView setRegion:region animated:TRUE];
 // Lastly, set the MKMapViewDelegate (we will use this later) 
  mapView.delegate = self;

 

3. Showing the user’s location

To show the user’s location on the map, we set this one special property.

 mapView.showsUserLocation = YES;

</p>

 

4. Creating custom annotations/landmarks

If you want to display some landmarks, aka annotations, on the map, you will need to create your annotation class that implement the MKAnnotation protocols.

Say you want to display some shops on the map, this is want you would do.

// ShopAnnotation.h
@interface ShopAnnotation : NSObject <mkannotation> {
 Shop *shop; // Assuming this class contains info about a shop
}
// ShopAnnotation.m  
// Required to implement
- (CLLocationCoordinate2D)coordinate {
  CLLocationCoordinate2D theCoordinate;
 theCoordinate.latitude = shop.latitude;
 theCoordinate.longitude = shop.longitude;
 return theCoordinate; 
}
 
// Optional
- (NSString *)title {
    return shop.name;
}
 
// Optional
- (NSString *)subtitle {
    return shop.address;
}

 

5. Adding annotations to the map

To add the annotations to the map, you would create the ShopAnnotation earlier and add them to mapView.

  for (Shop *shop in allMyShops) {
    ShopAnnotation *shopAnnotation = [[[ShopAnnotation alloc] initWithShop:shop] autorelease];
    [mapView addAnnotation:*shopAnnotation ];
 }

 

6. Handling the annotation views

Annotations are not views. After you added your annotations to the map, you would still need to provide its views. The mapView delegate methods will be called to ask for your annotations’ VIEWS. You will need to create the view and return it for mapView to display.

In our example, we create a MKPinAnnotationView, which is a standard pin that you see in Maps app. You could otherwise create your custom view that extends MKAnnotationView.

- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <mkannotation>)annotation {
  // If it's the user location, just return nil.
 if ([annotation isKindOfClass:[MKUserLocation class]])
    return nil;
 // If it is our ShopAnnotation, we create and return its view
 if ([annotation isKindOfClass:[ShopAnnotation class]]) {
    // try to dequeue an existing pin view first
    static NSString* shopAnnotationIdentifier = @"ShopAnnotationIdentifier";
    MKPinAnnotationView* pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:shopAnnotationIdentifier ];
    if (!pinView) {
     // If an existing pin view was not available, create one
      MKPinAnnotationView* customPinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:shopAnnotationIdentifier] autorelease];
      customPinView.pinColor = MKPinAnnotationColorRed;
     customPinView.animatesDrop = YES;
     customPinView.canShowCallout = YES;
 
      // add a detail disclosure button to the callout which will open a new view controller page
     UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
     customPinView.rightCalloutAccessoryView = rightButton;
 
      return customPinView;
   } else {
      pinView.annotation = annotation;
    }<strike></strike><strike></strike>
   return pinView;
 }
}

 

7. Selecting a pin

When a user selects a pin and press the UIButtonTypeDetailDisclosure button within the callout, we can present more details about the annotation. Implement another MKMapViewDelegate to handle this.

- (void)mapView:(MKMapView *)_mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
  // Handle it, such as showing another view controller
}

 

8. Open Maps app

If want to provide a route from the user location to the selected annotation, you would need the help of iPhone’s Maps app. This means that your app will exit and Maps app will be opened, with you telling Maps the source and destination to route.

You can open Maps with the schema as such.

 NSString *url = [NSString stringWithFormat:@"http://maps.google.com/maps?saddr=%f,%f&daddr=%f,%f";, userLatitude, userLongitude, [shop.latitude floatValue], [shop.longitude floatValue]];
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];

 

With that, we have come to the end of a few simple tasks with MapKit!