SDK for iOS Developer's Guide

Basic Positioning

An application created using SDK for iOS can use information from positioning capabilities of a user's device to display its position and, optionally, provide real-time updates. Getting the current position requires an application to make use of the NMAPositioningManager interface from HERE SDK. To receive position updates or position-lost notifications, an application should use NSNotificationCenter addObserver with the notification names found in NMAPositioningManager.h:
  • NMAPositioningManagerDidUpdatePositionNotification
  • NMAPositioningManagerDidLosePositionNotification

The user's current position can be easily displayed on the map using the NMAPositionIndicator class. Each instance of NMAMapView owns an instance of this class accessed via positionIndicator property.

NMAPositioningManager

The NMAPositioningManager class provides information related to the device geographical location such as the current position and the average speed. NMAPositioningManager is a singleton class and thus should only be accessed through the sharedPositioningManager class method.

To receive position updates, an object must subscribe to the NMAPositioningManager notifications. The notification update frequency can be controlled according to the data source which is set in dataSource property. By default, dataSource is an NMADevicePositionSource instance with one of the following NMADevicePositioningMethod convenience options to set the frequency of the device updates.

  • NMADevicePositioningMethodGPS - sends standard position updates as the location changes. These updates are provided by the iOS API CLLocationManager startUpdatingLocation.

  • NMADevicePositioningMethodSignificantChanges - sends position updates only when the user moves a significant distance. These updates are provided by the iOS API CLLocationManager startMonitoringSignificantLocationChanges. Use this option if you would like to save power.

Note: Add NSLocationWhenInUseUsageDescription to your project Info.plist so that CLLocationManager can properly access the user's location. The value of this key is displayed to the user when the system requests for permission to use location services. See App Submission Requirements for recommended strings.
Note: In addition to setting the dataSource to an NMADevicePositionSource you can also set it to a custom data source that conforms to the NMAPositionDataSource protocol. For more information on NMAPositionDataSource consult the API Reference.

To start receiving real time positioning updates, the application needs to call NMAPositioningManager startPositioning which uses NMADevicePositioningMethodGPS as the default update mechanism. This method returns a BOOL value indicating whether or not positioning was successfully started.

While position updates are being received, the application can retrieve the current position of the client device through NMAPositioningManager currentPosition property. This current position is equal to either rawPosition or mapMatchedPosition property, depending on which seems more likely to be correct under the current circumstances. rawPosition is a position value from the current data source that has not been modified by HERE SDK engine, while mapMatchedPosition is a position data value that is matched to the nearest car or pedestrian road, depending on mapMatchMode property. If the positioning manager is not active, or it has an invalid position, then currentPosition method returns nil.

Note: Map matching is disabled by default. It can be enabled automatically through the use of any HERE SDK feature which requires map matching, such as navigation, or it can be manually enabled by setting mapMatchingEnabled to YES. When map matching is disabled, mapMatchedPosition returns nil, and currentPosition returns the raw position.

When the application no longer requires position updates, it should notify the NMAPositioningManager by calling stopPositioning. Position updates are then stopped, provided that no other SDK services (such as NMAPositionIndicator) that require position updates are in use.

NMAPositioningManager Notifications

The NMAPositioningManager notifications can be used to track position updates of a client device as determined by its positioning mechanism (for example, its GPS). To register or unregister for these notifications, use the following methods:


[[NSNotificationCenter defaultCenter] addObserver:self
    selector:@selector(methodName)
      name:NMAPositioningManagerDidUpdatePositionNotification
      object:[NMAPositioningManager sharedPositioningManager]];

[[NSNotificationCenter defaultCenter] removeObserver:self
      name:NMAPositioningManagerDidUpdatePositionNotification
    object:[NMAPositioningManager sharedPositioningManager]];

Applications can register for two types of notifications:

  • NMAPositioningManagerDidUpdatePositionNotification
  • NMAPositioningManagerDidLosePositionNotification
Note: NSNotificationCenter does not limit how many times an object can register to the same notification. You should be careful not to register the same object more than once to a notification. Otherwise, the object receives duplicate notifications.

The following is an example of registering and handling these notifications in a UIViewController:


// Start positioning and register for position update notifications
- (void)viewDidLoad
{
  ...
  if ([[NMAPositioningManager sharedPositioningManager] startPositioning]) {
  // Register to positioning manager notifications
  [[NSNotificationCenter defaultCenter] addObserver:self
    selector:@selector(positionDidUpdate) name:NMAPositioningManagerDidUpdatePositionNotification
    object:[NMAPositioningManager sharedPositioningManager]];

  [[NSNotificationCenter defaultCenter] addObserver:self
    selector:@selector(didLosePosition) name: NMAPositioningManagerDidLosePositionNotification
    object:[NMAPositioningManager sharedPositioningManager]];
  }

  ...
}
// Handle NMAPositioningManagerDidUpdatePositionNotification
- (void)positionDidUpdate
{
  NMAGeoPosition *position = [[NMAPositioningManager sharedPositioningManager] currentPosition];
  [_mapView setGeoCenter:position.coordinates
        withAnimation:NMAMapAnimationLinear];
}
// Handle NMAPositioningManagerDidLosePositionNotification
- (void)didLosePosition
{
  ...
}

To avoid unnecessary position updates while the application is in the background, you can stop positioning and restart it when the application returns to the foreground using UIApplicationDelegate protocol callbacks.

The following code snippet demonstrates how to stop positioning and unregister from the notifications:


- (void)viewWillDisappear:(BOOL)animated
{
  [[NMAPositioningManager sharedPositioningManager] stopPositioning];
  [[NSNotificationCenter defaultCenter] removeObserver:self
    name:NMAPositioningManagerDidUpdatePositionNotification
    object:[NMAPositioningManager sharedPositioningManager]];
  [[NSNotificationCenter defaultCenter] removeObserver:self
    name:NMAPositioningManagerDidLosePositionNotification
    object:[NMAPositioningManager sharedPositioningManager]];
}
Note: Even if background location updates are enabled in your Xcode project, the NMAPositioningManager does not provide updates when your application is in the background unless there is an active navigation session. To override this behavior, call setBackgroundUpdatesEnabled:YES on NMAPositionDataSource.

Position Simulation

HERE SDK provides two classes, NMALoggedPositionSource and NMARoutePositionSource, which can be used to simulate position updates within an application. These classes implement the NMAPositionDataSource protocol; to use them, instances should be created, configured, and assigned to dataSource property of NMAPositioningManager. Only one position data source may be used at a time.

The NMALoggedPositionSource class provides positioning data from a log file. Currently, the GPX file format is supported. The positions listed in the log file are processed one by one until the end of the log is reached. stationary property simulates halting of movement along the logged path, and positionLost property simulates the loss of the position data.

The NMARoutePositionSource class provides positioning data from a calculated NMARoute. Updates are generated from the beginning to the end of the route with the frequency controlled by updateInterval property. The simulated travel speed is set using movementSpeed property. Stopping and losing position are simulated with stationary and positionLost properties respectively.

Note: NMALoggedPositionSource does not support indoor positioning.

Creating Position Logs

You can also use HERE SDK to create GPX logs that can be replayed by NMALoggedPositionSource. To do this, set logType property in NMAPositionManager to the value NMAPositionLogTypeDataSource indicating that the position received from the current data source should be logged. GPX logs are created in Documents folder of your application. To disable position logging, set NMAPositionLogType to NMAPositionLogTypeNone.

Note: This feature is only intended for debugging purposes. Do not use Position Logging in a production application.

NMAPositionIndicator

The NMAPositionIndicator class provides a convenient way to add a map object that marks the user's current location as reported by the NMAPositioningManager. The position indicator can be set to display the raw, map-matched, or current position (a position that is automatically selected between raw or map-matched). The position indicator is rendered as a circular object within a translucent circle, the diameter of which illustrates the accuracy of the indicated position. The types of map objects can be used to customize NMAPositionIndicator are NMAMapMarker , NMAMapLocalModel, and NMAMapCircle.

Figure 1. An NMAPositionIndicator

Each NMAMapView instance has an NMAPositionIndicator instance which can be accessed from NMAMapView positionIndicator property. The map object displayed by NMAPositionIndicator can be changed with its displayObject property, and the indicator can be shown or hidden with its visible property.

Note: You can use tracksCourse property to control whether the position indicator is automatically oriented to the current direction of movement. When enabled, HERE SDK rotates the positionIndicator to line up with the direction the vehicle is travelling in. In other words, if the vehicle is idle, there are no changes. If you need the position indicator to point to the device compass direction instead, use CLLocationManagerDelegate.

Note that orientationOffset is also only applicable when the positionIndicator yaw has changed based on the vehicle movement.

You can customize the accuracy circle color and whether it is visible by using accuracyIndicatorColor and accuracyIndicatorVisible properties.

// Display position indicator
mapView.positionIndicator.visible = YES;
Note: Setting NMAPositionIndicator to visible automatically enables NMAPositioningManager updates.

For the position indicator to stay in the center of the map and illustrate real-time updates of the device position, it is necessary to update the map center whenever a new location update is received. Please note that frequently re-drawing the map in this manner consumes device battery life. You should be aware of battery power implications while performing real-time updates. The following code can be used to update the map location when a position update is received:

- (void)positionDidUpdate
{
  NMAGeoPosition *position = [[NMAPositioningManager sharedPositioningManager] currentPosition];
  [_mapView setGeoCenter:position.coordinates
        withAnimation:NMAMapAnimationLinear];
}

For more information about the classes introduced and demonstrated in this section refer to the API reference documentation.