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.
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.
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.
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:
A map coordinate is a latitude and longitude on the spherical representation of the Earth. Map coordinates are the primary way of specifying locations on the globe. You specify individual map coordinate values using the CLLocationCoordinate2D
structure. You can specify areas using the MKCoordinateSpan
and MKCoordinateRegion
structures.
A map point is an x and y value on the Mercator map projection. Map points are used for many map-related calculations instead of map coordinates because they simplify the mathematics involved in the calculations. In your application, you use map points primarily when specifying the shape and position of custom map overlays. You specify individual map points using the MKMapPoint
structure. You can specify areas using the MKMapSize
and MKMapRect
structures.
A point is a graphical unit associated with the coordinate system of a UIView
object. Map points and map coordinates must be mapped to points before drawing custom content in a view. You specify individual points using the CGPoint
structure. You can specify areas using the CGSize
and CGRect
structures.
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.
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.
Convert from | Convert to | Conversion routines |
---|---|---|
Map coordinates | Points |
|
Map coordinates | Map points | |
Map points | Map coordinates | |
Map points | Points |
|
Points | Map coordinates |
|
Points | Map points |
|
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:
To add a map using Interface Builder, drag a Map view object to the appropriate view or window.
To add a map programmatically, create an instance of the MKMapView
class, initialize it using the initWithFrame:
method, and then add it as a subview to your view hierarchy.
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.”
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.
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 allow you to change the visible portion of the map at any time:
To pan the map (but keep the same zoom level), change the value in the centerCoordinate
property of the map view or call the setCenterCoordinate:animated:
method.
To change the zoom level (and optionally pan the map), change the value in the region
property of the map view or call the setRegion:animated:
method.
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]; |
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.
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:
Changes to the visible region of the map
The loading of map tiles from the network
Changes in the user’s location
Changes associated with annotations and overlays.
For information about handling changes associated with annotations and overlays, see “Annotating Maps.”
Last updated: 2010-05-20