Providing Directions

In iOS 6 and later, Map Kit offers support for providing map-based directions to the user. Apps can be a provider of directions or they can use the Maps app itself to provide directions. Apps that consume direction information do so by sending an appropriate request to the Maps app, which then handles the task of displaying that information to the user. However, if you are implementing a navigation app of your own, you can register your app as a routing app—that is, a provider of directions. When the Maps app receives direction requests from the user (or other apps), it can then forward those requests to your app for display.

Asking the Maps App to Display Directions

Map Kit provides a way for you to display specific map locations or turn-by-turn directions using the Maps app. This support allows apps to use the Maps app in situations where you might not want to display the map data yourself. For example, if your app does not have its own turn-by-turn navigation services, you can ask Maps to provide the information for you.

To generate a direction request, use the openMapsWithItems:launchOptions: or openInMapsWithLaunchOptions: method of MKMapItem. These methods let you send map items to the Maps app so that it can display them. If you include the MKLaunchOptionsDirectionsModeKey key with the launch options you pass to these methods, Maps displays directions between the start and end map items you provide.

Listing 6-1 shows a method that opens the specified region in the Maps app and centers the map on its location. You use the launchOptions parameter of the openMapsWithItems:launchOptions: method to specify the map region you want to display.

Listing 6-1  Displaying a location in the Maps app

- (void)displayRegionCenteredOnMapItem:(MKMapItem*)from {
   CLLocation* fromLocation = from.placemark.location;
 
   // Create a region centered on the starting point with a 10km span
   MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(fromLocation.coordinate, 10000, 10000);
 
   // Open the item in Maps, specifying the map region to display.
   [MKMapItem openMapsWithItems:[NSArray arrayWithObject:from]
              launchOptions:[NSDictionary dictionaryWithObjectsAndKeys:
                  [NSValue valueWithMKCoordinate:region.center], MKLaunchOptionsMapCenterKey,
                  [NSValue valueWithMKCoordinateSpan:region.span], MKLaunchOptionsMapSpanKey, nil]];
}

For information about how to open the Maps app programmatically, see MKMapItem Class Reference.

Registering as a Routing App

Apps that are able to display point-to-point directions can register as a routing app and make those directions available to the Maps app and to all other apps on a user’s device by extension. Registering as a routing app improves the user experience by giving other apps a means to access routing information from your app, thus avoiding the need for every app to provide its own routing directions. It is also a great way to get your app in front of the user. Maps always displays appropriate suggestions from the App Store as options for displaying directions.

To register your app as a directions provider, you must do the following:

Configuring Your App to Accept Direction Requests

To enable directions support for your app, you must configure the following support for your app target in Xcode:

  • Enable routing requests and specify the types of directions your app is capable of providing.

  • Configure a special document type to handle incoming routing requests.

You enable routing request support using the Accept transit routing requests checkbox in the Maps section of your target’s Summary tab. As part of enabling directions, you must specify the types of directions (pedestrian, car, subway, and so on) your app is able to provide. Enabling directions support adds the MKDirectionsApplicationSupportedModes key to your app’s Info.plist file and sets the value of that key to the transportation modes you select. You must also provide a GeoJSON file containing the regions for which your app is capable of providing directions. (For information about specifying the GeoJSON file, see “Declaring the Supported Geographic Coverage for Directions.”)

In addition to declaring the types of directions your app supports, you need to add a document type to your project whose purpose is to handle incoming routing requests. To add the document type, use the Xcode document type editor, located in the Info tab of your target. Create the new type and use the information in Table 6-1 to set the values for the type. You should use the values in the table exactly as they appear here.

Table 6-1  Keys and values for the directions request document type

Xcode field

Value

Description

Name

MKDirectionsRequest

The value in this field can be anything you want, but you are encouraged to use the suggested value.

Types

com.apple.maps.directionsrequest

The value of this key is a custom UTI type used to identify direction requests. The value of this key must be exactly as shown here.

The changes you make in the document types editor cause Xcode to add a corresponding entry to the CFBundleDocumentTypes key in your app’s Info.plist file. For more information about your app’s Info.plist file and the keys you put into it, see Information Property List Key Reference.

Declaring the Supported Geographic Coverage for Directions

Apps must declare the geographic regions for which they are capable of providing directions. Declaring the supported regions prevents the system from sending requests that your app is unable to handle. For example, if your app provides subway route information only for New York, you would not want it to receive requests to provide directions in London.

To declare your app’s supported regions, you must create a GeoJSON file, which is a type of JavaScript Object Notation (JSON) file. This is your app’s geographic coverage file and it contains a set of map coordinates that define the boundaries of one or more geographic regions. The format of this file is part of a public specification, the details of which you can obtain at http://geojson.org/geojson-spec.html.

Your geographic coverage file is used by the Maps app and the App Store, but not by your app. Uploading it to iTunes Connect makes it possible for Maps to look up apps on the App Store that are capable of providing directions in the target region. It can then provide the user with that information in case the user wants to download one of those apps. Because you upload it to iTunes Connect, you can also update the file at any time without submitting a new version of your app.

Specifying the Geographic Coverage File Contents

The geographic coverage file for an iOS app must contain a single MultiPolygon shape that defines the boundaries of the supported geographic regions. A single multi polygon may contain multiple child polygons, each of which defines the boundaries around a single geographic region. Each child polygon contains four or more coordinate values that define the boundaries of the polygon. Per the GeoJSON specification, every child polygon must represent a closed region—that is, the first and last coordinate values must always be identical. Therefore, you must specify at least four points to define a triangular region, which is the simplest possible shape. Of course, you can use include more points to define more complex polygons.

Listing 6-2 shows an example of a geographic coverage file that specifies two separate regions: one around San Francisco and one around Chicago. Note that the set of coordinates for each region are surrounded by what seem to be an extra set of brackets. In each case, the first open bracket marks the beginning of the overall polygon shape, the second open bracket defines the beginning of the exterior bounding polygon, and the third open bracket marks the beginning of the first coordinate. After closing the exterior bounding polygon, you could add additional sets of points that define holes in the polygonal region.

Listing 6-2  A sample GeoJSON file

{ "type": "MultiPolygon",
  "coordinates": [
    [[[-122.7, 37.3], [-121.9, 37.3], [-121.9, 37.9], [-122.7, 37.9], [-122.7, 37.3]]],
    [[[-87.9, 41.5], [-87.3, 41.5], [-87.3, 42.1], [-87.9, 42.1], [-87.9, 41.5]]]
    ]
}

Use the following guidelines to help you when defining the regions for your app:

  • Keep your regions simple and do not try to trace precise routes around a given geographic area. It is recommended that each polygon contain no more than 20 points. Using more coordinates to define a region is possible but is inefficient and usually unnecessary. The system has to determine whether a given point is inside one of your polygons, and it is cheaper to make that determination against a rectangle or other simple shape than it is against a shape with hundreds of points.

  • Limit the number of child polygons in your MultiPolygon shape to 20 or fewer.

  • Only specify regions for which you can provide useful directions to the user.

  • Use only MultiPolygon shape in your app’s coverage file. Although the GeoJSON specification supports other types of shapes, only MultiPolygon shapes are supported for routing apps.

  • Do not include comments in your coverage file.

  • All coordinates must be specified as a longitude followed by a latitude value.

  • The polygons in your coverage files must not include holes. Although holes are supported by the GeoJSON specification, they are not supported in Apple’s maps implementation.

Uploading Your GeoJSON File to iTunes Connect

When you upload your app to iTunes Connect, the server checks your app’s Info.plist file for the presence of the MKDirectionsApplicationSupportedModes key. If that key is present, the iTunes Connect page for your app includes a space for uploading your geographic coverage file. You must upload the file before your app can be approved. See “Uploading Icons, Screenshots, and Routing Files for Your App” in iTunes Connect Developer Guide for more information.

Debugging Your App’s Geographic Coverage File

During development, you use the scheme options of your Xcode project to specify the geographic coverage file to use during testing. When you run your app in the simulator, Xcode transfers this file to the simulator or device so that the Maps app knows about the regions your app supports. The content of this file should be identical to the file you plan to upload to iTunes Connect.

To specify the geographic coverage file for testing, do the following:

  1. Open the scheme editor for your project.

  2. Select the Run (Debug) scheme for your project.

  3. In the Options tab, select your coverage file from the Routing App Coverage File popup menu.

After installing your app on the device or simulator, exit your app and launch the Maps app to specify the start and end points for directions. Your app should appear if its geographic coverage file is valid and contains the two specified points. If it does not, check the points for your geographical regions to make sure they are correct.

Handling Direction Requests

The system sends direction requests to your app using URLs. When the user asks the Maps app for directions and chooses your app, Maps creates a URL with the start and end points and asks your app to open it. You handle the opening of this URL in your app’s application:openURL:sourceApplication:annotation: method, just like you would for other URLs. But the steps you take to process the URL are a little more prescribed.

When your app receives a URL to open, it should perform the following steps in its application:openURL:sourceApplication:annotation: method:

  1. Call the isDirectionsRequestURL: class method of MKDirectionsRequest to check whether the URL is a directions request URL. If it is a directions request, proceed with the remaining steps.

  2. Create an MKDirectionsRequest object using the provided URL.

  3. Obtain the start and end points of the route from the MKDirectionsRequest object.

    The start and end points are specified as MKMapItem objects, which contain the geographic coordinate of the location and possibly additional information. If the MKMapItem object represents the user’s current location, you need to use Core Location to retrieve the actual coordinate location data yourself.

  4. Compute and display the route using your custom routing technology.

Because the preceding steps are the same for every app, you can include code in your application:openURL:sourceApplication:annotation: method similar to that shown in Listing 6-3. The most important addition you must make is to compute the route information and display it in your app. If your app handles other URL types, you would also include code for processing those URLs separately.

Listing 6-3  Handling a directions request URL

- (BOOL)application:(UIApplication *)application
           openURL:(NSURL *)url
           sourceApplication:(NSString *)sourceApplication
           annotation:(id)annotation {
   if ([MKDirectionsRequest isDirectionsRequestURL:url]) {
      MKDirectionsRequest* directionsInfo = [[MKDirectionsRequest alloc] initWithContentsOfURL:url];
      // TO DO: Plot and display the route using the
      //   source and destination properties of directionsInfo.
      return YES;
   }
   else {
    // Handle other URL types...
   }
    return NO;
}

For additional information about using the MKDirectionsRequest class, see MKDirectionsRequest Class Reference.


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