HERE iOS SDK Developer's Guide

Maps

The core feature of the HERE iOS SDK is Mapping. The key concepts covered in this section include adding a map to an iOS application, changing the location displayed by the map, and modifying its properties. The primary component of the mapping API is the NMAMapView, which is integrated with the Cocoa Touch framework as a UIView subclass. NMAMapView represents the view to display map and various properties. The NMAMapView is derived from UIView and part of iOS Cocoa Touch framework.

Note: To create a simple map application, refer to the Quick Start section.

The first step to integrate a map into an application is to insert a NMAMapView to your view controller's .xib file or the storyboard of the application using the Interface Builder. Alternatively, you can also add NMAMapView to your view controller programmatically as follows:

- (void)viewDidLoad
{
  mapView = [[NMAMapView alloc] initWithFrame:self.view.frame];
  [self.view addSubview:mapView];
}

The NMAMapView class handles all user interactions in the form of touch gestures. More details about the supported gesture types can be found in the Map Gestures section.

Working with NMAMapView

Once the NMAMapView is initialized, it can be manipulated and interacted in a variety of ways. Some key attributes of the NMAMapView are its orientation, tilt, geographical center (geoCenter), and zoom level (zoomLevel). These properties may be used to customize the NMAMapView display. For example, the following code demonstrates how to show a view of Vancouver, Canada.

NMAGeoCoordinates *geoCoordCenter = [[NMAGeoCoordinates alloc]
  initWithLatitude:49.260327 longitude:-123.115025];
[self.mapView setGeoCenter:geoCoordCenter withAnimation:NMAMapAnimationNone];
In the preceding code:
  • The geographical location [NMAGeoCoordinates] for the new map center is created by a call to the -(id)initWithLatitude:(double)aLatitude longitude:(double)aLongitude method.
  • When setting the center of a map, the transition can be animated by passing either the NMAMapAnimationLinear or the NMAMapAnimationBow enum value to the animation parameter. Animation can also be suppressed by using the NMAMapAnimationNone value.

The beginning and ending of these events may be observed by assigning an object to the NMAMapView's delegate property. The object should implement the methods of the NMAMapViewDelegate protocol corresponding to the events you wish it to receive. This delegate can also be used to detect map object selection.

Note: For optimum performance, avoid resizing a map after it has been created. If resizing is necessary, create the map at the largest size to be used and reduce it later.

Map Projection Mode

By default, the map is set to a globe projection mode. You can change it to use Mercator projection by setting the projectionType property. For example:
mapView.projectionType = NMAProjectionTypeMercator;
It may be useful to set the projection modes when you need to predictably display certain types of map information, such as custom raster tiles.
Figure 1. Globe Projection
Figure 2. Mercator Projection

Map Snapshots

The NMAMapView class provides a class method and an instance method for creating map snapshots. These methods allow developers to create small, static maps—such as thumbnails—that use the latest data from the HERE SDK.
  • +(void)snapshotWithGeoCoordinates:(NMAGeoCoordinates*)coordinates
                zoomLevel:(float)zoom
                orientation:(float)orientation
                size:(CGSize)size
                block:(void (^)(UIImage *snapshot))resultBlock; 
  • -(void)snapshotWithBlock:(void (^)(UIImage *snapshot))resultBlock;
For more information on using these methods, consult the API reference.

Properties of NMAMapView

The following examples show how to work with some of the properties in NMAMapView:

Map Center

The center of the map determines the geographical area to be displayed. It can be read using the NMAMapView geoCenter property, and set using one of the setGeoCenter: methods. Its type is NMAGeoCoordinates.

// Move the map to London.
NMAGeoCoordinates *geoCoordCenter = [[NMAGeoCoordinates alloc]
initWithLatitude:51.51 longitude:-0.11];
[self.mapView setGeoCenter:geoCoordCenter withAnimation:NMAMapAnimationNone];

Zoom Level

The size of the geographical area displayed by the map can be controlled by changing the zoom level. The zoom level ranges from NMAMapView::minimumZoomLevel to NMAMapViewMaximumZoomLevel, with a higher zoom value being closer to the ground. The following code sets the zoom level to the median zoom level:

// Set the zoom level to the median.
mapView.zoomLevel =
(mapView.minimumZoomLevel + NMAMapViewMaximumZoomLevel)/2.0f;
Note: The NMAMapView::minimumZoomLevel property provides the effective minimum zoom level depending on the current map and device display parameters, such as display resolution. To retrieve the minimum zoom level that does not take these parameters into account, use NMAMapViewMinimumZoomLevel.

Orientation

The orientation determines which cardinal direction corresponds with which screen direction of the NMAMapView. The valid range is from 0 to 360 degrees. The default value of 0 orients the map so that true north is toward the top of the view. The following code shows how to set the orientation to south-up:

// Rotate 180 degrees.
mapView.orientation = 180;

Tilt

The tilt value represents the angle at which the map is viewed. By default, the map tilt value is 0. This provides a top-down two-dimensional view of the map. You can set a tilt value using the tilt property in NMAMapView, but since the valid range of tilt values is dependent on the current zoom level, this tilt property is converted before it is used on screen. You can also use the maximumTiltProfile property in NMAMapView to specify a block and define how zoom levels affect the maximum tilt.

To find the actual tilt value that is being used, call the clippedTilt accessor method. To find the tilt limits for a given zoom level, call the minimumTiltAtZoomLevel: and maximumTiltAtZoomLevel: methods.

// Set the tilt to 45 degrees
mapView.tilt = 45;

Animations

The NMAMapView supports the following animation settings to be used while changing properties, defined by the NMAMapAnimation enum:

  • NMAMapAnimationNone
  • NMAMapAnimationLinear
  • NMAMapAnimationRocket
  • NMAMapAnimationBow
// Rotate 90 degrees using a linear animation
[mapView setOrientation:90 withAnimation:NMAMapAnimationLinear];
// Move to London using bow animation
NMAGeoCoordinates *geoCoordCenter = [[NMAGeoCoordinates alloc]
    initWithLatitude:51.51 longitude:-0.11];
[mapView setGeoCenter:geoCoordCenter withAnimation:NMAMapAnimationLinear];

Setting Multiple Attributes

An extended API is provided to change one or more attributes at the same time.

-(void) setGeoCenter:(NMAGeoCoordinates*) coordinates
           zoomLevel:(float) level
           orientation:(float) orientation
              tilt:(float) tilt
         withAnimation:(NMAMapAnimation) animation

To leave a map attribute unchanged, pass the NMAMapViewPreserveValue constant to the relevant method parameter.

// Move to Vancouver using bow animation, zoom level 17, 180
// degree orientation and preserve tilt.
NMAGeoCoordinates* coord = [[NMAGeoCoordinates alloc]
  initWithLatitude:49.0
  longitude:123.0];
[mapView setGeoCenter:coord
  zoomLevel:17.0f
  orientation:180
  tilt:NMAMapViewPreserveValue
  withAnimation:NMAMapAnimationBow];

Map Event Blocks

Map event blocks provide a simple and versatile way to add custom handling for map events. With this mechanism, an application can have arbitrary code executed when a specific map event occurs. Your application can define this code using NMAMapEventBlock. Each block can be registered to respond to one or more events, and it can dynamically control whether it continues to respond to a particular event type.

Note: The functionality of a map event block may overlap with NMAMapViewDelegate callbacks. In these situations, it is recommended that you use NMAMapEventBlock to implement custom map event handling.
The types of event that can be observed are represented by the NMAMapEvent enum and include:
  • geoCenter has changed
  • zoomLevel has changed
  • orientation has changed
  • tilt has changed
  • A gesture has begun
  • A gesture has ended
  • An animation has begun
  • An animation has ended
  • Transformation has begun
  • Transformation has ended

Transformation refers to any changes to the map geocenter, zoom level, orientation, and tilt value, regardless of whether the change was caused by the user or the application. There may be multiple transformations from different sources, including animations, gestures and others, between a single set of transformation begin and transformation end events. For example, if the application triggers a map animation, and the map was in a stationary state, then the NMAMapEventTransformationBegan and NMAMapEventAnimationBegan events occurs. If the user then performs a gesture before the animation completes, then the NMAMapEventAnimationEnded and NMAMapEventGestureBegan events occurs. Finally, when the user finishes the gesture, the NMAMapEventGestureEnded and the NMAMapEventTransformationEnded events occurs.

To register a map event block, use the respondToEvents:withBlock: method and set the events that you would like the block to respond to. For example, to hide an overlay whenever there is a map gesture or animation:

[_mapView respondToEvents:(NMAMapEventGestureBegan | NMAMapEventAnimationBegan) withBlock:^(NMAMapEvent event, NMAMapView *mapView, id eventData) {
  // _myOverlay is an informative overlay on the map
  _myOverlay.hidden = YES;
  return YES;
}];

[_mapView respondToEvents:(NMAMapEventGestureEnded | NMAMapEventAnimationEnded) withBlock:^(NMAMapEvent event, NMAMapView *mapView, id eventData) {
  // _myOverlay is an informative overlay on the map
  _myOverlay.hidden = NO;
  return YES;
}];

If the event block returns YES, the event block continues to run when the relevant event is triggered. If the event block returns NO, then it is removed for that particular triggering event. (If the same block is also registered for other event types, then it still responds to those events.) For example, the following code only performs a one-off action when the current animation finishes:

[_mapView respondToEvents:NMAMapEventAnimationEnded withBlock:^(NMAMapEvent event, NMAMapView *mapView, id eventData) {
  // Do something...
  return NO;  // This block will be removed after being called once
}];

The respondToEvents:withBlock: method returns a unique integer value to identify the registered block. To unregister the block, call removeEventBlockWithIdentifier: with this integer value.

Note: When creating event handler blocks, care should be taken to avoid retain cycles. Any objects strongly referenced in the block is not released as long as the block remains. This includes any explicit or implicit (such as through an instance variable) references to self. Ensure that any strongly referenced objects inside the block are meant to live as long as the block does; if not, use a weak reference.

Map Display Layers

Map information such as street labels and park names are grouped as display layers. These layers are grouped as categories and represented by the NMAMapLayerCategory enums. By default, all layers are enabled to be displayed on the map view, and you can use the following NMAMapView methods to control whether they should be hidden.

  • isMapLayerCategoryVisible: - check whether a category of map layers is visible
  • setVisibility:forMapLayerCategories: - sets whether the specified categories of map layers should be visible
  • visibleMapLayerCategories - retrieves an NSArray representing the currently visible categories of map layers

For a full list of map display layer categories, see the API Reference for NMAMapLayerCategory.

Categories of Places

NMAMapView provides the following methods to show and hide categories of places on the map. Categories of places are represented by the NMAMapPoiCategory enum.
  • poiCategories - retrieves the names of all place categories
  • setVisibility:forPoiCategory: - sets whether a category of places is visible
  • isPoiCategoryVisible: - check whether a category of places is visible
For example, you can hide all gas stations by calling the following:

[mapview setVisibility:NO forPoiCategory:NMAMapPoiCategoryPetrolStation];

Pedestrian Features

By default, icons that indicate pedestrian access features (such as stairs or escalators) are not displayed on the NMAMapView. To display a pedestrian feature on the map view, call the showPedestrianFeature:pedestrianFeature method with the desired NMAMapPedestrianFeatureType. Similarly, you can hide a pedestrian feature by calling hidePedestrianFeature:pedestrianFeature method. To find out whether a feature type is enabled, call the isPedestrianFeatureShown:pedestrianFeature method.

Figure 3. Pedestrian Feature Icons

Interruption Handling

By default, NMAMapView pauses map rendering when the application is no longer in the active state, such as while displaying the Control Center menu or while receiving a system notification. You can disable this behaviour by setting the pauseOnWillResignActive property to NO. If automatic pausing is disabled, the application must manually pause the map view rendering when it goes to the background by setting the renderAllowed property to NO.

Note: Rendering must be paused before returning from the applicationDidEnterBackground method of UIApplicationDelegate.

For more information about the APIs introduced and demonstrated in this section, refer to the API Reference documentation.