Find places and addresses

This topic describes how to build an OS X application to find places and addresses and show them on a map. It's assumed that you've already added a map to your application as described in Add a map to your app.

The API provides a locator (class name AGSLocator) that allows you to match addresses and place names to locations on a map (also known as geocoding), and conversely, match locations on a map to real world addresses (also known as reverse geocoding).

Learn more about the Locator

The locator relies on Esri's geocode web services, which can be hosted in Esri's cloud platform (ArcGIS Online) or on your on-premise servers. In this topic, you'll use Esri's World geocode web service on ArcGIS Online.

1. Allow a user to input an address or place name

First, you'll modify the user interface (UI) to allow a user to input the name of a place or an address. To do this, you'll add a search field to the window and create a corresponding property (IBOutlet) to access the search field's properties. Next, connect the search field to an IBAction, such as findAddress:. This will allow the app to respond whenever the user enters an address or place name in the field.


We do not need incremental search for the purpose of this topic (searching at every key stroke). So to ensure that the whole string is searched for change the Behavior of the search field to be 'Sends Whole Search String'.


2. Find matching locations

When the user types in a location or an address and hits the Return Key the findAddress: method is invoked. This method will search for the address or place using the locator provided by Esri's World geocode web service on ArcGIS Online.

Firstly adopt the AGSLocatorDelegate protocol; create a property for the locator, and instantiate it to Esri’s World Geocode Locator. Adopt the AGSLocatorDelegate protocol and instantiate the locator. A locator delegate is required to handle the results of the locator (a task). We must assign the current class (self) to be the locator's delegate.

class AppDelegate: NSObject, NSApplicationDelegate, AGSMapViewLayerDelegate, AGSLocatorDelegate {
 var locator:AGSLocator!

func applicationDidFinishLaunching(aNotification: NSNotification) {
 //init the arcgis locator and set delegate
 self.locator = AGSLocator()
 self.locator.delegate = self

You can define input parameters and format of results using AGSLocatorFindParameters class. Instantiate an object of this class, “set the text property to be the address/place string provided by the search field". Set the results of the locator to have the same spatial reference as the mapView and ensure that all fields are output. Now, execute the locator's findWithParameters: method passing in these parameters.

@IBAction func findAddress(sender: AnyObject) {
 //if search field has string value then continue
 if !(self.searchField.stringValue == "") || (!self.searchField.stringValue.isEmpty) {
  //setup find parameters
  var findParams = AGSLocatorFindParameters()
  findParams.text = self.searchField.stringValue
  findParams.outFields = ["*"]
  findParams.outSpatialReference = self.mapView.spatialReference
  //execute find

Implement the methods of AGSLocatorDelegate – didFind: and didFailToFindWithError: to handle the results of a search. So when the findWithParameters: method completes, didFind: or didFailToFindWithError: are called and the results or errors are returned to the user.

func locator(locator: AGSLocator!, operation op: NSOperation!, didFind results: [AnyObject]!) {

func locator(locator: AGSLocator!, operation op: NSOperation!, didFailLocationsForAddress error: NSError!) {

3. Display locations on the map

In this section, you'll add the results returned by the locator to the map. First, instantiate a graphics layer. Assign a simple renderer to the graphics layer so that each graphic in it is drawn as a blue point. Add the graphics layer to the map. Setting up the graphics layer could be done in applicationDidFinishLaunching: method.

//Assign a simple renderer to the layer to display results as pushpins
var symbol = AGSSimpleMarkerSymbol(color: NSColor(red: 0, green: 0.46, blue: 0.68, alpha: 1))
symbol.size = CGSizeMake(7, 7) = .Circle
symbol.outline = nil
//Add the graphics layer
self.graphicsLayer = AGSGraphicsLayer()
self.graphicsLayer.renderer = AGSSimpleRenderer(symbol: symbol)
self.mapView.addMapLayer(self.graphicsLayer, withName:"Results")

When the locator completes its operation the didFind: method of AGSLocatorDelegate returns the results as an array of AGSLocatorFindResult objects. First check whether the results array is empty, and if so, inform the user that no results were found. If results were found, you'll iterate through them and add the graphic corresponding to each result to the graphics layer. Finally, you'll zoom in on the map to the results.

func locator(locator: AGSLocator!, operation op: NSOperation!, didFind results: [AnyObject]!) {
 //remove all graphics from graphics layer
 if results == nil || results.count == 0 {
  var alert = NSAlert()
  alert.messageText = "No Results"
  alert.informativeText = "No results found by locator"
  alert.beginSheetModalForWindow(self.window, modalDelegate: self, didEndSelector: nil, contextInfo: nil)
 else {
  var graphics = Array<AGSGraphic>()
  //Add a graphic for each result
  for findResult in results as [AGSLocatorFindResult] {
   var graphic = findResult.graphic
  //add graphics to graphics layer
  //zoom to graphics layer
  self.mapView.zoomToGeometry(self.graphicsLayer.fullEnvelope, withPadding: 100, animated: true)

4. Run the application

At this point, you've written all the code required to allow a user to enter an address or place name and display its location on a map. All you need to do now is run the application. It should look like this.

Find London