Displaying Maps
While obtaining the location coordinates of a position is interesting, such information is much more useful if you can visually locate it on a map. Fortunately, the iPhone SDK 3.0 ships with the Map Kit API, which makes displaying Google Maps in your application a snap. Here's an example.
Using the same project you created in the previous section, add a Button view to the View window in the LBSViewController.xib file (see Figure 3).
Right-click on the Frameworks group in Xcode and add a new framework called MapKit.framework.
Add the statement shown below in bold to the LBSViewController.h file:
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
@interface LBSViewController : UIViewController
<CLLocationManagerDelegate> {
IBOutlet UITextField *accuracyTextField;
IBOutlet UITextField *latitudeTextField;
IBOutlet UITextField *longitudeTextField;
CLLocationManager *lm;
MKMapView *mapView;
}
@property (retain, nonatomic) UITextField *accuracyTextField;
@property (retain, nonatomic) UITextField *latitudeTextField;
@property (retain, nonatomic) UITextField *longitudeTextField;
-(IBAction) btnViewMap: (id) sender;
@end
Back in Interface Builder, control-click, and drag the Button view to the File's Owner item, and then select btnViewMap:.
In the LBSViewController.m file, add the statements in bold from the following code:
-(IBAction) btnViewMap: (id) sender {
[self.view addSubview:mapView];
}
- (void) viewDidLoad {
lm = [[CLLocationManager alloc] init];
lm.delegate = self;
lm.desiredAccuracy = kCLLocationAccuracyBest;
lm.distanceFilter = 1000.0f;
[lm startUpdatingLocation];
mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
mapView.mapType = MKMapTypeHybrid;
}
- (void) locationManager: (CLLocationManager *) manager
didUpdateToLocation: (CLLocation *) newLocation
fromLocation: (CLLocation *) oldLocation{
NSString *lat = [[NSString alloc] initWithFormat:@"%g",
newLocation.coordinate.latitude];
latitudeTextField.text = lat;
NSString *lng = [[NSString alloc] initWithFormat:@"%g",
newLocation.coordinate.longitude];
longitudeTextField.text = lng;
NSString *acc = [[NSString alloc] initWithFormat:@"%g",
newLocation.horizontalAccuracy];
accuracyTextField.text = acc;
[acc release];
[lat release];
[lng release];
MKCoordinateSpan span;
span.latitudeDelta=.005;
span.longitudeDelta=.005;
MKCoordinateRegion region;
region.center = newLocation.coordinate;
region.span=span;
[mapView setRegion:region animated:TRUE];
}
- (void) dealloc{
[mapView release];
[lm release];
[latitudeTextField release];
[longitudeTextField release];
[accuracyTextField release];
[super dealloc];
}
Basically, the preceding code:
- Creates an instance of the MKMapView class when the view has loaded, and sets the map type (hybrid: map and satellite in this case) to display.
- Adds the mapView object to the current view when a user taps the View Map button.
- Zooms into the location using the mapView object's setRegion: method whenever the location information gets updated.
Press Command-r to test the application on the iPhone Simulator. Now, tapping on the View Map button will show a map containing the location reported by the location manager (see Figure 4).
Because the simulator always provides the same fixed location, this is as far as you can go without testing on a real device. When you do that, you'll be able to see the map update itself dynamically as you move the device around. Be sure to alter the distanceFilter property to a smaller number so that you will be able to track small changes in distance.
As you've seen, the iPhone SDK's Core Location framework makes it easy to implement location-based services. In addition, the MapKit (also in the iPhone 3.0 SDK) makes displaying maps a snap. If you have not yet had an opportunity to build a location-based application, you're coming to the field at the right time. With all these new features, now is the perfect time to begin!