Working with Maps on iOS 7 with MapKit and the MKMapView Class

From Techotopia
Revision as of 14:43, 5 May 2016 by Neil (Talk | contribs) (Text replacement - "<table border="0" cellspacing="0" width="100%">" to "<table border="0" cellspacing="0">")

Jump to: navigation, search
PreviousTable of ContentsNext
An Example iOS 7 Location ApplicationWorking with MapKit Local Search in iOS 7


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book


In the preceding chapters we spent some time looking at handling raw geographical location information in the form of longitude, latitude and altitude data. The next step is to learn about the presentation of location information to the user in the form of maps and satellite images. The goal of this chapter, therefore, is to provide an overview of the steps necessary to present the application user with location, map and satellite imagery using the MapKit framework and, in particular, the MKMapView class. In the next chapters, this example application will be extended to make use of the Map Kit local search and directions features.


Contents


About the MapKit Framework

The MapKit Framework is based on the Apple Maps data and APIs and provides iOS developers with a simple mechanism for integrating detailed and interactive mapping capabilities into any application.

The core element of the MapKit framework from the point of view of the app developer is the MKMapView class. This class is a subclass of UIView and provides a canvas onto which map and satellite information may be presented to the user. Information may be presented in map, satellite or hybrid (whereby the map is superimposed onto the satellite image) form. The displayed geographical region may be changed manually by the user via a process of pinching stretching and panning gestures, or programmatically from within the application code via method calls and property manipulation on the MkMapView instance. The current location of the device may also be displayed and tracked on the map view.

The MapKit framework also includes support for adding annotations to a map. This takes the form of a pin or custom image, title and subview that may be used to mark specific locations on a map.

Implementation of the MKMapViewDelegate protocol allows an application to receive notifications of events relating to the map view such as a change in either the location of the user or region of the map displayed or the failure of the device to identify the user’s current location or to download map data.

Understanding Map Regions

The area of the map that is currently displayed to the user is referred to as the region. This is defined in terms of a center location (declared by longitude and latitude) and span of the surrounding area to be displayed. Adjusting the span has the effect of zooming in and out of the map relative to the specified center location. The region’s span may be specified using either distance (in meters) or coordinate based degrees. When using degrees, one degree of latitude is equivalent to 111 km. Latitude, however, varies depending on the longitudinal distance from the equator. Given this complexity, the map view tutorial in this chapter will declare the span in terms of distance.


About the MKMapView Tutorial

The objective of this tutorial is to develop an iOS application designed to display a map with a marker indicating the user’s current location. Buttons located in a navigation bar are provided to allow the user to zoom in on the current location and to toggle between map and satellite views. Through the implementation of the MKMapViewDelegate protocol the map will update as the user’s location changes so that the current location marker is always the center point of the displayed map region.

Creating the Map Project

Begin by launching Xcode and creating a new iOS project named MapSample using the Single View Application template configured either for the iPhone or iPad.

Adding the MapKit Framework to the Xcode Project

Since we will be making use of the MapKit framework during this tutorial the first step is to add the framework to the project. To achieve this, select the application target at the top of the project navigator panel. In the resulting project settings panel, select the Build Phases tab and unfold the Link Binary with Libraries section. Click on the ‘+’ button, locate the MapKit.framework entry from the resulting list and click Add.

Adding the Navigation Controller

Later stages of this tutorial will require the services of a navigation controller. Since the presence of the navigation bar will have implications for the layout of the user interface of the main view, it make sense to add the controller now. Select the Main.storyboard file from the project navigator panel and select the view controller view so that it highlights in blue and use the Editor -> Embed In -> Navigation Controller menu option to embed a controller into the storyboard as illustrated in Figure 70-1:


The Storyboard for an iOS 7 MapView example app

Figure 70-1


Creating the MKMapView Instance and Toolbar

The next step is to create an instance of the MKMapView class we will be using in our application and to add a toolbar instance to the user interface. Remaining in the Main.storyboard file, drag a Toolbar from the Object Library and place it at the bottom of the view canvas.

Next, drag and drop a Map View object onto the canvas and resize and position it so that it takes up the remaining space in the view above the toolbar and below the navigation bar. By default the Interface Builder tool will have added a single Bar Button Item to the new toolbar. For the purposes of this example, however, two buttons will be required so drag and drop a second Bar Button Item from the Object Library panel onto the toolbar. Double click on the toolbar button items and change the text to “Zoom” and “Type” respectively:


The UI for an iOS 7 MapView example App

Figure 70-2


Select the view controller by clicking on the status bar containing the battery indicator so that the scene is highlighted in blue. Select the Resolve Auto Layout Issues menu from the toolbar in the lower right hand corner of the storyboard canvas and select the Reset to Suggested Constraints in Map Sample View Controller menu option. Select the MKMapView object in the view canvas, display the Assistant Editor panel and verify that the editor is displaying the contents of the MapSampleViewController.h file. Ctrl-click on the MKMapView object and drag to a position just below the @interface line in the Assistant Editor. Release the line and in the resulting connection dialog establish an outlet connection named mapView.

Click on the “Zoom” button to select it (note that in order to select a toolbar button item it may be necessary to click on it twice since the first click selects the toolbar parent). With the button item selected, Ctrl-click on the button object and drag the line to the area immediately beneath the newly created outlet in the Assistant Editor panel. Release the line and, within the resulting connection dialog, establish an Action method on the Touch Up Inside event configured to call a method named zoomIn. Repeat this step to connect the “Type” button to a method named changeMapType.

Select the MapSampleViewController.h file from the project navigator panel and verify that the outlets and actions have been set up correctly. Also take this opportunity to import the <MapKit/MapKit.h> file and to declare the class as implementing the <MKMapViewDelegate> protocol:

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>

@interface MapSampleViewController : UIViewController
    <MKMapViewDelegate>

@property (strong, nonatomic) IBOutlet MKMapView *mapView;
- (IBAction)zoomIn:(id)sender;
- (IBAction)changeMapType:(id)sender;
@end

<google>ADSDAQBOX_FLOW</google> Perform a test run of the application’s progress so far by clicking on the Run button in the Xcode toolbar. The application should run in the iOS simulator as illustrated in Figure 70-3:


An iOS 7 MapView instance showing the United States

Figure 70-3


Configuring the Map View

By default the Map View does not indicate the user’s current location. By setting the showsUserLocation property of the MKMapView class the map is instructed to display a representation of the current location on the map in the form of a blue translucent ball. In order to set this property, select the MapSampleViewController.m file and locate and modify the viewDidLoad method as follows:

- (void)viewDidLoad
{
    [super viewDidLoad];
    _mapView.showsUserLocation = YES;
    
}

Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book

Changing the MapView Region

When the Zoom button is tapped by the user the map view region needs to be changed so that the user’s current location is set as the center location and the region span needs to be changed to 20000 meters (analogous to zooming in to the map region). The code to implement this belongs in the zoomIn method which now needs to be implemented in the mapSampleViewController.m file:

- (IBAction)zoomIn:(id)sender {
    MKUserLocation *userLocation = _mapView.userLocation;
    MKCoordinateRegion region =
       MKCoordinateRegionMakeWithDistance (
          userLocation.location.coordinate, 20000, 20000);
    [_mapView setRegion:region animated:NO];
}

This method performs some very simple operations in order to achieve the desired effect in the mapView object. Firstly, the user’s current location is ascertained by accessing the userLocation property of the map view object. This is stored in the form of an MKUserLocation object which, in turn, contains the coordinates of the user. Next, the MKCoordinateRegionMakeWithDistance function is called in order to generate an MKCoordinateRegion object consisting of the user’s location coordinates and a span that stretches 20000 meters both to the North and South of the current location. Finally, this region object is passed through to the setRegion method of the mapView object.

Now that the Zoom functionality has been implemented it is time to configure the map type switching feature of the application.

Changing the Map Type

The map type of a map view is controlled by the object’s mapType property. Supported values for this property are MKMapTypeStandard, MKMapTypeSatellite and MKMapTypeHybrid. For the purposes of this example application the map will switch between standard and satellite modes. Within the MapSampleViewController.m file modify the changeMapType action method connected to the Type button as follows:

- (IBAction)changeMapType:(id)sender {
    if (_mapView.mapType == MKMapTypeStandard)
        _mapView.mapType = MKMapTypeSatellite;
    else
        _mapView.mapType = MKMapTypeStandard;
} 

This very simple method simply toggles between the two map types when the button is tapped by the user.

Testing the MapView Application

Now that more functionality has been implemented, it is a good time to build and run the application again so click on the Xcode Run button to load the application into the iOS Simulator. Once the application has loaded, a blue dot should appear over Northern California. Since the application is running in the simulator environment, the location information is simulated to match either the coordinates of Apple’s headquarters in Cupertino, CA, or another simulated location depending on the current setting of the Debug -> Location menu. Select the Type button to display the satellite view and then zoom in to get a better look at the region:


An iOS 7 MapView instance in satellite mode zoomed in

Figure 70-4


To get real location information, load the application onto a physical iOS device (details of which can be found in the Testing Apps on iOS 7 Devices with Xcode 5 chapter of this book).

Updating the Map View based on User Movement

Assuming that you installed the application on a physical iOS device and went somewhere with the device in your possession (or used one of the debug location settings that simulated movement) you may have noticed that the map did not update as your location changed and that the blue dot marking your current location eventually went off the screen (also assuming, of course, that you had zoomed in to a significant degree).

In order to configure the application so that the map automatically tracks the movements of the user, the first step is to make sure the application is notified when the location changes. At the start of this tutorial the view controller was declared as conforming to the MKMapViewDelegate delegate protocol. One of the methods that comprise this protocol is the didUpdateUserLocation method. When implemented, this method is called by the map view object whenever the location of the device changes. We must, therefore, first specify that the MapSampleViewController class is the delegate for the mapView object, which can be performed by adding the following line to the viewDidLoad method located in the MapSampleViewController.m file:

_mapView.delegate = self; 

The next task involves the implementation of the didUpdateUserLocation method in the MapSampleViewController.m file:

- (void)mapView:(MKMapView *)mapView 
didUpdateUserLocation:
(MKUserLocation *)userLocation
{
    _mapView.centerCoordinate = 
          userLocation.location.coordinate;
} 

The delegate method is passed as an argument an MKUserLocation object containing the current location coordinates of the user. This value is simply assigned to the center coordinate property of the mapView object such that the current location remains at the center of the region. When the application is now installed and run on a device the current location will no longer move outside the displayed region as the device location changes. To experience this effect within the simulator, simply select the Debug -> Location -> Freeway Drive menu option and then select the Zoom button in the user interface.

Summary

This chapter has demonstrated the basics of using the MKMapView class to display map based information to the user within an iOS 7 application. The example created in the chapter also highlighted the steps involved in zooming into a region of the map, changing the map display type and configuring a map to track the user’s current location.

The next chapter will explore the use of the local search feature of the MapKit framework before extending the example application to mark all the locations of a specified business type on the map.


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book



PreviousTable of ContentsNext
An Example iOS 7 Location ApplicationWorking with MapKit Local Search in iOS 7