Locator

The Locator allows you to geocode addresses and reverse-geocode locations using ArcGIS Server Geocode Services. Geocoding an address involves finding a matching location on the Earth’s surface for that address. Reverse-geocoding is the exact opposite. It involves finding corresponding addresses for a given location on a map.

Geocode services are based on address locators. Address locators may reside in an ArcGIS Geodatabase or as *.loc files on disk. They rely on GIS datasets and other reference data to find addresses and locations. Each address locator uses an address style for parsing addresses and standardizing them into well-structured address components. You use ArcMap or ArcCatalog to create new address locators. You can then publish them as Geocode services using ArcMap or ArcCatalog, or using ArcGIS Server’s Manager web application.

ArcGIS Server Geocode services are accessible on the web as SOAP and REST web services. The REST web service supports two operations – Find Address Candidates, and Reverse Geocode. The locator in the ArcGIS API for iOS uses these operations to achieve its functionality. While publishing a Geocode service, the administrator may decide to disable either of these operations. You should verify that the service you intend to use provides the functionality your desire.

To successfully use the locator, you must know

You can use the ArcGIS Server Services Directory to find out details about the service you wish to use. You can easily find out what operations are supported.

Locator operations
Infact, if you're familiar with the REST API, you can even invoke operations on the service directly from a browser using the Services Directory.

Creating the locator

To instantiate an AGSLocator, you need to provide a URL to a Geocode service REST endpoint. This URL is usually of the form http://<server:port>/<instance>/services/<service>/GeocodeServer. If the web service is secured, you will also need to provide the credentials that can be used to access the service. In this tutorial, we’ll be using the ESRI_Geocode_USA service from a sample server on ArcGIS Online.

NSURL* url = [NSURL URLWithString: @"http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Locators/ESRI_Geocode_USA/GeocodeServer";
AGSLocator* locator = [[AGSLocator alloc] initWithURL: url];

When you create the locator, you need to ensure you take ownership of it. Otherwise, it might get deallocated before it has a chance to execute. If you instantiate the task using alloc as shown above , you automatically have ownership. However, if you instantiate the task using a convenience constructor, such as locatorWithURL: , you need to take ownership by either sending it a retainmessage, or by assigning it to a property that will retain it.

When you are finished using the locator, you should relinquish ownership so that it’s memory can be reclaimed. You do this either by sending the task a release message or by setting the corresponding property to nil.

NoteNote:

Please refer to Apple's Memory Management Programming Guide for more information on how to manage application memory.

Geocoding an address

To find matching locations for an address, you must provide an NSDictionary object containing the address in a format expected by the service. The format is listed in the Address Fields section in the Services Directory. Only fields that are required must be specified. Others may be omitted.

Address Fields

For the service we’re using, we need to specify Address, City, State and Zip.

NSDictionary *address = [NSDictionary dictionaryWithObjectsAndKeys: @"380 New York St", @"Address", @"Redlands", @"City", @"CA", @"State", @"92373", @"Zip",  nil];

If you want to geocode an intersection of two streets instead of a business or a home, you need to use a permitted connector to specify the streets. This connector is listed in the Locator Properties section of Services Directory. The service we are using allows using the symbols &, |, or @ as connectors.

NSDictionary *address = [NSDictionary dictionaryWithObjectsAndKeys: @"380 New York St", @"Address", @"Redlands", @"City", @"CA", @"State", @"92373", @"Zip",  nil];

You also need to specify which fields should be returned when a matching location is found. The fields available to you are listed in the Candidate Fields section of the Services Directory. If the address you’re geocoding is an intersection, use the Intersection Candidate Fields section instead.

Candidate fieldsIntersection Candidate fields

Services from ArcGIS Server 10 or above allow you to use the * wildcard to get all the fields. For older servers, you need to explicitly specify each field.

NSArray *outFields = [NSArray arrayWithObjects: @"Shape", @"Score", @"Match_addr", @"Side ", @"HouseNum", @"StreetName", @"StreetType", @"City","State", @"Zip", nil];

You can also optionally specify the output spatial reference. This is the spatial reference in which the matching location(s) should be returned to you. By default, the location(s) returned to you will have the same spatial reference as that of the service. By explicitly specifying a different spatial reference, the Geocode service can re-project the location(s) so that you can easily display them on your map.This is useful, for example, when the Geocode service uses a spatial reference that is different from the spatial reference of your map

AGSSpatialReference* outSR = [AGSSpatialReference spatialReferenceWithWKID:4326 WKT:nil];
[locator locationsForAddress:address returnFields:outfields outSpatialReference:outSR];

Reverse geocoding a location

To find address candidates for a location, you need to provide a point representing the location. If the point does not have a spatial reference, the Geocode service will assume it is in the spatial reference of the service. You also need to provide a maximum search distance (in meters) within which to search for address candidates from the given location. You can optionally specify an output spatial reference in which the address candidates should be returned.

AGSPoint* point = [AGSPoint pointWithX: -117.195681386 y: 34.057517097 spatialReference:[AGSSpatialReference spatialReferenceWithWKID:4326 WKT:nil]];
[locator addressForLocation:point maxSearchDistance:100];

Getting results and handling errors

The locator informs its delegate when operations complete successfully or when errors are encountered. To get results from the locator and to properly handle any errors, you must set one of your classes as the locator’s delegate. You do this by making your class (typically the view controller which uses the locator) adopt the AGSLocatorDelegate protocol.

@interface MyViewController : UIViewController <AGSLocatorDelegate> {  
  ...
}

An instance of your class must also be set as the locator’s delegate. This will allow the locator to invoke methods on your class in response to operations that it performs.

locator.delegate = self;

Finally, your class must implement one or more methods defined in the protocol which pertain to the operation being performed. For geocoding operations, the delegate should implement the locator:operation:didFindLocationsForAddress: method to be informed when the operation finishes successfully. Results of the operation are passed to the delegate method as an array of AGSAddressCandidate objects.

- (void) locator:(AGSLocator*) locator operation:(NSOperation*) op didFindLocationsForAddress:(NSArray*) candidates {
   for (AGSAddressCandidate* candidate in candidates) {
     NSLog(@"Candidate : %@",candidate);  
   }
}

To be informed of failure, the delegate should implement the locator:operation:didFailLocationsForAddress: method. The reason for failure is passed to the method as an NSError object.

- (void) locator:(AGSLocator*) locator operation:(NSOperation*) op didFailLocationsForAddress:(NSError*) error { 
   NSLog(@"Error: %@",error); 
}

See also

12/7/2011