iOS Reference Library Apple Developer
Search

Displaying Maps

Introduced in iOS 3.0, the Map Kit framework lets you embed a fully functional map interface into your application. The map support provided by this framework includes many of the features normally found in the Maps application. You can display standard street-level map information, satellite imagery, or a combination of the two. You can zoom and pan the map programmatically, and the framework provides automatic support for the touch events that let users zoom and pan the map. You can also annotate the map with custom information.

To use the features of the Map Kit framework, you must link your application to MapKit.framework in your Xcode project. To access the classes and headers of the framework, include an #import <MapKit/MapKit.h> statement at the top of any relevant source files. For general information about the classes of the Map Kit framework, see Map Kit Framework Reference.

Important: The Map Kit framework uses Google services to provide map data. Use of the framework and its associated interfaces binds you to the Google Maps/Google Earth API terms of service. You can find these terms of service at http://code.google.com/apis/maps/iphone/terms.html.

Understanding Map Geometry

A map view contains a flattened representation of a spherical object, namely the Earth. In order to use maps effectively, you need to understand a little bit about how to specify points in a map view, and how those points translate to points on the Earth’s surface. Understanding map coordinate systems is especially important if you plan to place custom content, such as overlays, on top of the map.

Map Coordinate Systems

In order to understand the coordinate systems used by Map Kit, it helps to understand how the three-dimensional surface of the Earth is mapped to a two-dimensional map. Figure 4-1 shows how the surface of the Earth can be mapped to a two-dimensional surface.

Figure 4-1  Mapping spherical data to a flat surface

Map Kit uses a Mercator map projection, which is a specific type of cylindrical map projection like the one shown in Figure 4-1. In a cylindrical map projection, the coordinates of a sphere are mapped onto the surface of a cylinder, which is then unwrapped to generate a flat map. In such a projection, the longitude lines that normally converge at the poles become parallel instead, causing land masses to be distorted as you move away from the equator. The advantage of a Mercator projection is that the map content is scaled in a way that benefits general navigation. Specifically, on a Mercator map projection, a straight line drawn between any two points on the map yields a course heading that can be used in actual navigation on the surface of the Earth. The projection used by Map Kit uses the Prime Meridian as its central meridian.

How you specify data points on a map depends on how you intend to use them. Map Kit supports three basic coordinate systems for specifying map data points:

In most situations, the coordinate system you should use is predetermined by the Map Kit interfaces you are using. When it comes to storing actual data in files or inside your application, map coordinates are precise, portable, and the best option for storing location data. Core Location also uses map coordinates when specifying location values.

Converting Between Coordinate Systems

Although you normally specify points on the map using latitude and longitude values, there may be times when you need to convert to and from other coordinate systems. For example, you typically use map points when specifying the shape of overlays. Table 4-1 lists the conversion routines you use to convert from one coordinate system to another. Most of these conversions require a view object because they involve converting to or from points.

Table 4-1  Map coordinate system conversion routines

Convert from

Convert to

Conversion routines

Map coordinates

Points

convertCoordinate:toPointToView: (MKMapView)

convertRegion:toRectToView: (MKMapView)

Map coordinates

Map points

MKMapPointForCoordinate

Map points

Map coordinates

MKCoordinateForMapPoint

MKCoordinateRegionForMapRect

Map points

Points

pointForMapPoint: (MKOverlayView)

rectForMapRect: (MKOverlayView)

Points

Map coordinates

convertPoint:toCoordinateFromView: (MKMapView)

convertRect:toRegionFromView: (MKMapView)

Points

Map points

mapPointForPoint: (MKOverlayView)

mapRectForRect: (MKOverlayView)

Adding a Map View to Your User Interface

The MKMapView class is a self-contained interface for presenting map data in your application. This class provides support for displaying map data, for managing user interactions, and for hosting custom content provided by your application. You should never subclass MKMapView but should only embed it as-is into your application’s view hierarchy. You should also assign a delegate object to the map. The map view reports all relevant interactions to its delegate so that it has a chance to respond appropriately.

You can add a map view to your application programmatically or using Interface Builder:

Because it is a view, you can manipulate a map view in the same ways you manipulate other views. You can change its size and position in your view hierarchy, you can configure its autoresizing behaviors, and you can add subviews to it. Unlike a view, you never handle touch events directly in a map view. The map view itself is an opaque container for a complex view hierarchy that handles the display of map-related data and all interactions with that data. Any subviews you add to the map view retain the position specified by their frame property and do not scroll with the map contents. If you want content to remain fixed relative to a specific map coordinate (and thus scroll with the map itself), you must use annotations or overlays as described in “Annotating Maps.”

New maps are configured to accept user interactions and display map data only. You can configure the map to display satellite imagery or a mixture of satellite and map data by changing the Type attribute of the map in Interface Builder or changing the value in the mapType property. If you want to limit user interactions, you can change the values in the zoomEnabled and scrollEnabled properties as well. If you want to respond to user interactions, you should do so using a delegate as described in “Responding to User Interactions with a Map.”

Configuring the Properties of a Map

The MKMapView class has a handful of properties that you can configure programmatically. These properties control important information such as which part of the map is currently visible and what user interactions are allowed.

Setting the Visible Portion of the Map

The region property of the MKMapView class controls the currently visible portion of the map. When it is first created, a map’s visible region is typically set to the entire world. In other words, the region encompasses the area that shows as much of the map as possible. You can change this region at any time by assigning a new value to the region property. This property contains an MKCoordinateRegion structure, which has the following definition:

typedef struct {
   CLLocationCoordinate2D center;
   MKCoordinateSpan span;
} MKCoordinateRegion;

The interesting part of an MKCoordinateRegion structure is the span. The span is analogous to the width and height values of a rectangle but is specified using map coordinates and thus is measured in degrees, minutes, and seconds. One degree of latitude is equivalent to approximately 111 kilometers but longitudinal distances vary with the latitude. At the equator, one degree of longitude is equivalent to approximately 111 kilometers but at the poles this value is zero. If you prefer to specify the span using meters, you can use the MKCoordinateRegionMakeWithDistance to create a region data structure using meter values instead of degrees.

The value you assign to the region property (or set using the setRegion:animated: method) is usually not the same value that is eventually stored by that property. Setting the span of a region nominally defines the rectangle you want to view but also implicitly sets the zoom level for the map view itself. The map view cannot display arbitrary zoom levels and must adjust any regions you specify to match the zoom levels it supports. It chooses the zoom level that allows your entire region to be visible while still filling as much of the screen as possible. It then adjust the region property accordingly. To find out the resulting region without actually changing the value in the region property, you can use the regionThatFits: method of the map view.

Zooming and Panning the Map Content

Zooming and panning allow you to change the visible portion of the map at any time:

If you only want to pan the map, you should only do so by modifying the centerCoordinate property. Attempting to pan the map by changing the region property usually causes a change in the zoom level as well, because changing any part of the region causes the map view to evaluate the zoom level needed to display that region appropriately. Changes to the current latitude almost always cause the zoom level to change and other changes might cause a different zoom level to be chosen as well. Using the centerCoordinate property (or the setCenterCoordinate:animated: method) lets the map view know that it should leave the zoom level unchanged and update the span as needed. For example, to pan the map to the left by half the current map width, you could use the following code to find the coordinate at the left edge of the map and use that as the new center point, as shown here:

CLLocationCoordinate2D mapCenter = myMapView.centerCoordinate;
mapCenter = [myMapView convertPoint:
               CGPointMake(1, (myMapView.frame.size.height/2.0))
               toCoordinateFromView:myMapView];
[myMapView setCenterCoordinate:mapCenter animated:YES];

To zoom the map, modify the span of the visible map region. To zoom in, assign a smaller value to the span. To zoom out, assign a larger value. In other words if the current span is one degree, specifying a span of two degrees zooms out by a factor of two:

MKCoordinateRegion theRegion = myMapView.region;
 
// Zoom out
theRegion.span.longitudeDelta *= 2.0;
theRegion.span.latitudeDelta *= 2.0;
[myMapView setRegion:theRegion animated:YES];

Displaying the User’s Current Location on the Map

Map Kit includes built-in support for displaying the user’s current location on the map. To show this location, set the showsUserLocation property of your map view object to YES. Doing so causes the map view to use Core Location to find the user’s location and add an annotation of type MKUserLocation to the map.

The addition of the MKUserLocation annotation object to the map is reported by the delegate in the same way that custom annotations are. If you want to associate a custom annotation view with the user’s location, you should return that view from your delegate object’s mapView:viewForAnnotation: method. If you want to use the default annotation view, you should return nil from that method instead.

Responding to User Interactions with a Map

The MKMapView class reports significant map-related events to its associated delegate object. The delegate object is an object that conforms to the MKMapViewDelegate protocol. You provide this object in situations where you want to respond to the following types of events:

For information about handling changes associated with annotations and overlays, see “Annotating Maps.”




Last updated: 2010-05-20

Did this document help you? Yes It's good, but... Not helpful...