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!