SDK for iOS Developer's Guide

Geocoding and Reverse Geocoding

Geocoding and reverse geocoding APIs from SDK for iOS allow application developers to offer search functionality for requesting NMAPlaceLocation information. Geocoding APIs resolve a free-formatted text query to an NMAGeoCoordinates, while reverse geocoding APIs resolve from an NMAGeoCoordinates to geographic data such as NMAAddress.

NMAAddress provides textual address information including house number, street name, city, country, district, and more. It encompasses everything about an address or a point on the map. The NMAPlaceLocation class represents an area on the map where additional attributes can be retrieved. These additional attributes include NMAAddress, unique identifier, label, location, access locations, and NMAGeoBoundingBox for the location.

Geocoding and Reverse Geocoding Example on GitHub

You can find an example that demonstrates this feature at https://github.com/heremaps/ (Obj-C) and https://github.com/heremaps/ (Swift).

The NMAGeocoder Interface

The NMAGeocoder interface represents a factory class used to instantiate location search requests. Two types of requests are available: NMAGeocodeRequest and NMAReverseGeocodeRequest.

The NMAGeocodeRequest Interface

The NMAGeocodeRequest interface represents an extended NMARequest. The NMAGeocodeRequest can be created using a combination of a search area and a free text query string. This is known as a "one-box" request. It returns NMAPlaceLocation results according to the specified search area and text query. You can specify a search area by providing an NMAGeoBoundingBox or a location with a search radius.

The following shows the methods used to create one-box requests:

NMAGeocodeRequest* request = [[NMAGeocoder sharedGeocoder] createGeocodeRequestWithQuery:string
            searchArea:geoBoundingBox
            locationContext:geoCoordinates];
NMAGeocodeRequest* request = [[NMAGeocoder sharedGeocoder] createGeocodeRequestWithQuery:string
            searchRadius:radius
            locationContext:geoCoordinates];

The preceding methods return an NMAGeocodeRequest object. To perform the request, call its startWithListener: method. The parameter of this method is an object which receives the request results; the object must implement the NMAResultListener protocol. Once a request is invoked, it can be cancelled using cancel method of NMARequest, which returns a BOOL value indicating whether the result was cancelled successfully. If the NMAGeocodeRequest is successful, a list of NMAGeocodeResult objects is returned to the listener.

The following code example demonstrates how to use an NMAGeocodeRequest:


// Implementation of NMAResultListener
@interface NMAGeocodeTest : NSObject<NMAResultListener> {
}
@end
@implementation NMAGeocodeTest

// NMAResultListener protocol callback implementation
- (void)request:(NMARequest*)request
    didCompleteWithData:(id)data
    error:(NSError*)error
{
  if ( ( [request isKindOfClass:[NMAGeocodeRequest class]]) &&
    ( error.code == NMARequestErrorNone ) )
  {
    // Process result NSArray of NMAGeocodeResult objects
    [self processResult:(NSMutableArray *)data];
  }
  else
  {
    // Handle error
    ...
  }
}

- (void) startSearch
{
  NMAGeoCoordinates *topLeft =
    [[NMAGeoCoordinates alloc]
      initWithLatitude:52.537413 longitude:13.365641];
  NMAGeoCoordinates *bottomRight =
    [[NMAGeoCoordinates alloc]
      initWithLatitude:52.522428 longitude:13.39345];
  NMAGeoBoundingBox *boundingBox =
    [NMAGeoBoundingBox
      geoBoundingBoxWithTopLeft:topLeft bottomRight:bottomRight];

  NMAGeocodeRequest* request = [[NMAGeocoder sharedGeocoder]
  createGeocodeRequestWithQuery:@"100 INVALIDENSTRASSE"
            searchArea:boundingBox
            locationContext:nil];

  // limit the number of results to 10
  request.collectionSize = 10;

  NSError* error = [request startWithListener:self];
  if (error.code != NMARequestErrorNone)
  {
    // Handle request error
    ...
  }
}
@end

The NMAReverseGeocodeRequest interface

The NMAReverseGeocodeRequest interface represents an extended NMARequest used to retrieve NMAPlaceLocation data. The request is created using an NMAGeoCoordinates as shown below:

NMAGeocodeRequest* request = [[NMAGeocoder sharedGeocoder]
  createReverseGeocodeRequestWithGeoCoordinates:geoCoordinates];

The above method returns an NMAReverseGeocodeRequest object. Reverse geocode requests are used in the same way as regular geocode requests (described in the previous section) but the results are returned as an array of NMAReverseGeocodeResult objects.

The following example shows how to create and use an NMAReverseGeocodeRequest:


// Implementation of NMAResultListener
@interface NMAReverseGeocodeTest : NSObject<NMAResultListener> {
}
@end
@implementation NMAReverseGeocodeTest

// NMAResultListener protocol callback implementation
- (void)request:(NMARequest*)request
  didCompleteWithData:(id)data
  error:(NSError*)error
{
  if ( ( [request isKindOfClass:[NMAReverseGeocodeRequest class]]) &&
    ( error.code == NMARequestErrorNone ) )
  {
    // Process result NSArray of NMAReverseGeocodeResult objects
    [self processResult:(NSMutableArray *)data];
  }
  else
  {
    // Handle error
    ...
  }
}

- (void) startSearch
{
  // Instantiate an Address object
  NMAGeoCoordinates* vancouver = [[NMAGeoCoordinates alloc] initWithLatitude:49.2849 longitude:-123.1252];

  NMAReverseGeocodeRequest* request = [[NMAGeocoder sharedGeocoder] createReverseGeocodeRequestWithGeoCoordinates:vancouver];

  NSError* error = [request startWithListener:self];
  if (error.code != NMARequestErrorNone)
  {
    // Handle request error
    ...
  }
}

@end

By default the reverse geocode request above searches for the closest street address. Alternatively, you can also create a reverse geocoding request in one of the following modes (NMAReverseGeocodeMode):

  • NMAReverseGeocodeModeRetrieveAddresses - Search for the closest street address or addresses (same as above)
  • NMAReverseGeocodeModeRetrieveAreas - Retrieve the administrative area information for the position provided in the request
  • NMAReverseGeocodeModeRetrieveLandmarks - Search for landmarks like parks and lakes in the proximity provided in the request
  • NMAReverseGeocodeModeRetrieveAll - Search for streets, administrative areas, and landmarks. This mode aggregates the results of the previous three modes in one call
  • NMAReverseGeocodeModeTrackPosition - Retrieve street and address information based on a position and bearing

See the following for an example of how to use this type of request. Note that bearing parameter is only used when you use NMAReverseGeocodeModeTrackPosition.

NMAReverseGeocodeRequest* request = [[NMAGeocoder sharedGeocoder]
  createReverseGeocodeRequestWithGeoCoordinates:geoCoordinates
  mode:NMAReverseGeocodeModeRetrieveLandmarks
  bearing:0];

[request startWithBlock:^(NMARequest *request, id data, NSError *error) {
    if(!error) {
      NSArray *results = (NSArray*)data;
      NMAReverseGeocodeResult *result = nil;
      NSMutableString *address = [NSMutableString new];

      for (NSUInteger i = 0; i < results.count; i ++) {
        result = [results objectAtIndex:i];

        [address appendFormat:@"%ld.\n", i + 1];

        if (result.distance > 0) {
          [address appendFormat:@"distance:%.2f\n", result.distance];
        }
        if (result.location.address.houseNumber) {
          [address appendFormat:@"houseNo:%@\n", result.location.address.houseNumber];
        }
        if (result.location.address.street) {
          [address appendFormat:@"street:%@\n", result.location.address.street];
        }
        if (result.location.address.city) {
          [address appendFormat:@"city:%@\n", result.location.address.city];
        }
        if (result.location.address.state) {
          [address appendFormat:@"state:%@\n", result.location.address.state];
        }
        if (result.location.address.postalCode) {
          [address appendFormat:@"postalCode:%@\n", result.location.address.postalCode];
        }
        if (result.location.address.countryName) {
          [address appendFormat:@"country:%@\n", result.location.address.countryName];
        }
        if (result.location.timeZone) {
          [address appendFormat:@"timeZone:%@\n\n", result.location.timeZone.name];
        }
      }
    }
   }];

Offline Geocoding

Applications developed with SDK for iOS can perform offline geocoding, which allows geocode and reverse geocode requests to be performed without an active data connection. This is done automatically when an active data connection is not available as long as the map and database information has been previously downloaded. When a data connection is available, HERE SDK attempts to perform the request online first.

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