This article is based on iPhone and iPad in Action, published on August, 2010. It is being reproduced here by permission from Manning Publications. Manning publishes MEAP (Manning Early Access Program,) eBooks and pBooks. MEAPs are sold exclusively through Manning.com. All pBook purchases include free PDF, mobi and epub. When mobile formats become available all customers will be contacted and upgraded. Visit Manning.com for more information. [ Use promotional code ‘java40beat’ and get 40% discount on eBooks and pBooks ]
Adding a map to an application
Introduction
Adding a map to any application is very similar to adding any other view. You can either do it through Interface Builder or programmatically. The choice is up to you depending on how you like to work with UI elements. We will show you both methods.
The view that displays a map is called MKMapView. This class contains quite a bit of functionality including how to display the map, annotations, and user location. We will first be discussing how to add an MKMapView through Interface Builder. Once we add the map to the view, we will connect it to an IBOutlet and set its delegate class.
Adding the map using Interface Builder
Before you start coding the MKMapView, you must first import MapKit.framework. This will provide you will all of the libraries needed to work with maps.
To add a map to your view, your must first create an MKMapView IBOutlet in the class that will be using the map. Listing 1 shows how to do this.
Listing 1 Declaring an IBOutlet for an MKMapView
#import <UIKit/UIKit.h> #import <MapKit/MapKit.h> @interface SimpleMapViewController : UIViewController<MKMapViewDelegate> { IBOutlet MKMapView * theMap; }
@property (nonatomic, retain) IBOutlet MKMapView * theMap;
The first thing we want to point out is you must import the MapKit.h header file. This is included in MapKit.framework and is needed for all MapKit interaction. The second is, our class implements the MKMapViewDelegate interface. It will allow this class to become the delegate of the MKMapView and receive messages from it. In addition to making a property, you should also synthesize the map property in the .m file.
Now that the IBOutlet has been declared, you need to add the MKMapView to the view in the nib file. To do this open up the nib file associated with the class that contains your IBOutlet. Now, select MKMapView from the Library and drag it on to your view. Figure 1 shows what this object should look like.
Figure 1 Adding an MKMapView to your viewWhen you drag the map on to you view, you are able to move and resize it however you like. Now that it has been added, you must connect it to the IBOutlet. To do this, click on the File’s Owner object and open the Connections Inspector. Now, drag from the map outlet to the map view to make the connection.
The last thing that needs to be done is set the delegate of the MKMapView. To do this, right click on the map and drag to the File’s Owner object. It should pop up a bubble that reads, “delegate”. Click the word delegate to make the connection. Figure 2 shows what the Connection Inspector should look like after you have completed all of these steps.
Figure 2 Connection inspector for the MKMapView connectionsAs you can see, adding an MKMapView using Interface Building is about the same as adding UILabels, UITextFields, and other view elements. Now that you have seen how to add the map visually, we will show you how to add one programmatically.
Adding the map programmatically
As noted before, whether you add the map using Interface Builder or with code is up to you. It is completely dependent on your preferences and organization technique. Listing 2 demonstrates how to add an MKMapView to your view controller’s view using code.
Listing 2 Adding an MKMapView programmatically
- (void)viewDidLoad { [super viewDidLoad]; MKMapView * map = [[MKMapView alloc] initWithFrame: CGRectMake(0, 0, 320, 480)]; Map.delegate = self; [self.view addSubview:map]; }
This code is actually quite short. We create the map using a frame, set its delegate to our class, and add it to our class’ view. As with any other view, modifying the frame passed to the map will alter its size and position.
Controlling the map
By default, the map has gives the user a bit of control. Without any additional code, they have the ability to scroll all over the world by flicking the map. Also, the map comes with the ability to zoom in and out by using the pinch and pull gestures.
To navigate the map programmatically, you must specify a region. Doing this will allow you to move the map to a specified location. You will also have the ability to set the zoom level.
Let’s examine the region properties and methods for navigating the map. Table 1 discusses these properties and methods and their uses.
The code below shows you how to create an MKCoordinateRegion and move the map to display it on the screen. The method we created here fires when a user presses a button titled Apple. It will move the map from its current location to center on Apple’s headquarters in Cupertino.
Listing 3 moving the map to a given location
- (IBAction) apple:(id) sender { CLLocationCoordinate2D coords; coords.latitude = 37.33188; coords.longitude = -122.029497; MKCoordinateSpan span = MKCoordinateSpanMake(0.002389, 0.005681); MKCoordinateRegion region = MKCoordinateRegionMake(coords, span); [theMap setRegion:region animated:YES]; }
The first thing we see here is a CLLocationCoordinate2D being created. This is simply a struct that holds two doubles for latitude and longitude. Next, we assign them to the coordinates of Apple using the WGS 84 reference frame.
Following the coordinates, we create a span using the MKCoordinateSpanMake method. An MKCoordinateSpan is a struct made of two doubles that represent a delta for latitude and longitude. The span represents the amount of area to view and is used when setting the zoom level. A larger number here tells the map to show a larger view area resulting in the map zooming out. Similarly, a smaller number tells the map to show less area and causes it to zoom in.
Once the coordinates and span have been initialized, we can create a region using the MKCoordinateRegionMake method. Finally, we set the region of the map to our newly created one and animate the transition. In addition to controlling the map’s location, you can also control how the user can interact with it. Table 2 details these properties.
As mentioned above, the mapType property allows you to display the map in three different ways. Most likely, you will want to make this configurable by the user, as preferences tend to vary about how the map should display. Figure 3 shows the difference between the map types.
Figure 3 mapTypes: (from left to right) MKMapTypeStandard, MKMapTypeSattelite, MKMapTypeHybridAs you can see, you have quite a bit of control over how the map looks. The standard map view looks very much like a road map that you would use for navigation. This is often the most useful of the map types.
The other two are quite similar. The only difference between them is the hybrid view contains the road names in addition to displaying the satellite photos.