HERE iOS SDK Developer's Guide

Basic Positioning

An application created using the HERE iOS SDK can use information from the 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 the HERE SDK. In order 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 the positionIndicator property.

NMAPositioningManager

The NMAPositioningManager class provides information related to the device's 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.

Note: Add NSLocationWhenInUseUsageDescription to your project's 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.

To start receiving real time positioning updates, the application needs to call NMAPositioningManager startPositioning, which uses the internal GPS as the 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 the NMAPositioningManager currentPosition property. This current position is equal to the rawPosition property. rawPosition is a position value from the current data source that has not been modified by the HERE SDK engine. If the positioning manager is not active, or it has an invalid position, then the 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
{
  ...
}

In order 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: If you enable background location updates in the Xcode project, then NMAPositioningManager provides position updates even when your application is no longer in the foreground. To avoid this behavior, you can either stop the positioning manager before the app goes into the background, or you can disable this setting in Xcode.

Creating Position Logs

You can also use the HERE SDK to create GPX logs that can be replayed by NMALoggedPositionSource. To do this, set the 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 the 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 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 and NMAMapCircle.

Figure 1. An NMAPositionIndicator

Each NMAMapView instance has an NMAPositionIndicator instance which can be accessed from the NMAMapView positionIndicator property.

You can customize the accuracy circle's color and whether it is visible by using the 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's center whenever a new location update is received. Please note that frequently redrawing 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.